diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..be441d2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +# Binary benchmark artifacts +*.pptx binary +*.png binary +*.ttf binary +*.ttc binary +*.mp4 binary + +# Preserve licensed text and prompt-significant whitespace verbatim. +acidslide-v1/benchmark/fonts/licenses/** -whitespace +acidslide-v1/benchmark/prompts/variants/** -whitespace diff --git a/.github/ISSUE_TEMPLATE/benchmark-case.yml b/.github/ISSUE_TEMPLATE/benchmark-case.yml new file mode 100644 index 0000000..79b8414 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/benchmark-case.yml @@ -0,0 +1,50 @@ +name: Propose a benchmark case +description: Add a slide behavior that generated PowerPoint artifacts should prove. +title: "[case]: " +labels: ["benchmark-case"] +body: + - type: markdown + attributes: + value: | + Thanks for making the corpus harder. Requirements must come from a public prompt, reference, or allowed asset — never from reverse-engineering the gold deck. + - type: textarea + id: failure + attributes: + label: What fails today? + description: Describe the generated deck behavior a screenshot or current check misses. + placeholder: A chart looks correct but is stored as a picture, so its data cannot be edited. + validations: + required: true + - type: textarea + id: requirement + attributes: + label: Proposed requirement + description: State the observable visual and/or native artifact requirement. + validations: + required: true + - type: dropdown + id: layer + attributes: + label: Primary layer + options: + - Native OOXML / package structure + - Rendered visual fidelity + - Both + validations: + required: true + - type: textarea + id: evidence + attributes: + label: Public source and evidence plan + description: Link the prompt/reference/asset source and describe a positive control plus a single-fault negative fixture. + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Contribution checks + options: + - label: I can share every attached artifact under the repository license or its stated compatible license. + required: true + - label: This proposal does not contain private decks, credentials, customer data, or proprietary fonts. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..e5e8476 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Security vulnerability + url: https://github.com/aronchick/gloss/security/advisories/new + about: Report security issues privately, never in a public issue. + - name: Contribution guide + url: https://github.com/aronchick/gloss/blob/main/CONTRIBUTING.md + about: Read the evidence and fixture requirements before opening a pull request. diff --git a/.github/ISSUE_TEMPLATE/evidence-challenge.yml b/.github/ISSUE_TEMPLATE/evidence-challenge.yml new file mode 100644 index 0000000..436abb8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/evidence-challenge.yml @@ -0,0 +1,37 @@ +name: Challenge evidence or a claim +description: Question provenance, a mutation operator, a scoring assumption, or release wording. +title: "[evidence]: " +labels: ["evidence"] +body: + - type: input + id: claim + attributes: + label: Claim or evidence ID + placeholder: gloss-technical-preview-2026-07-22 or a repository path + validations: + required: true + - type: textarea + id: challenge + attributes: + label: What does the current evidence fail to establish? + description: Separate observed facts from your interpretation. + validations: + required: true + - type: textarea + id: falsify + attributes: + label: How can we test or falsify it? + description: Propose a fixture, review, independent reproduction, or wording change. + validations: + required: true + - type: dropdown + id: urgency + attributes: + label: Release impact + options: + - Blocks any public claim + - Blocks an official benchmark freeze + - Improves the technical preview + - Documentation only + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/grader-bug.yml b/.github/ISSUE_TEMPLATE/grader-bug.yml new file mode 100644 index 0000000..30f9f18 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/grader-bug.yml @@ -0,0 +1,46 @@ +name: Report a grader gap +description: Reproduce a false positive, false negative, crash, or nondeterministic result. +title: "[grader]: " +labels: ["grader"] +body: + - type: textarea + id: behavior + attributes: + label: Observable behavior + description: What did Gloss report, and what should it have reported? + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Minimal reproduction + description: Include exact `uv` commands, tier, platform, and a minimal safe fixture or repository path. + render: shell + validations: + required: true + - type: input + id: commit + attributes: + label: Gloss commit + placeholder: 40-character Git SHA + validations: + required: true + - type: dropdown + id: impact + attributes: + label: Result + options: + - False positive + - False negative + - Crash or incomplete verification + - Nondeterministic result + - Other + validations: + required: true + - type: checkboxes + id: safety + attributes: + label: Safety + options: + - label: This is not a security vulnerability. I will use the private process in SECURITY.md for vulnerabilities. + required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..5bafe2f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ +## What changed + + + +## Evidence + + + +## Verification + +```text +Exact commands run: + +Results: +``` + +## Release truth + +- [ ] Public claims in this pull request are traceable to committed evidence. +- [ ] I did not imply that Draft candidate checks or local scores are official leaderboard results. +- [ ] Grader behavior changes include focused tests or fixtures. +- [ ] I checked for private decks, credentials, customer data, and proprietary fonts. +- [ ] Documentation reflects any new command, contract, or contribution path. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8d471c2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,127 @@ +name: CI + +on: + push: + branches: [main] + tags: ["acidslide-v*"] + pull_request: + +permissions: + contents: read + +jobs: + grader: + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: acidslide-v1/grader + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v6 + with: + version: "0.8.4" + enable-cache: true + - run: uv sync --extra dev --locked + - run: uv run ruff check . + - run: uv run ruff format --check . + - run: uv run mypy acidslide tests + - run: uv run pytest --cov=acidslide --cov-report=term-missing --cov-fail-under=85 + - run: uv build + - run: uv run pip-audit + - name: Verify self-contained wheel data + run: | + uv run python -m zipfile -l dist/acidslide-1.0.0a1-py3-none-any.whl | grep 'acidslide/data/benchmark/checklist/deck.yaml' + uv run python -m zipfile -l dist/acidslide-1.0.0a1-py3-none-any.whl | grep 'acidslide/data/schemas/ecma-376/xsd-transitional/pml.xsd' + + corpus: + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: acidslide-v1/grader + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v6 + with: + version: "0.8.4" + enable-cache: true + - run: uv sync --extra dev --locked + - run: uv run python ../benchmark/validate_corpus.py + - name: Require the complete frozen release on version tags + if: startsWith(github.ref, 'refs/tags/acidslide-v') + run: | + test "$GITHUB_REF_NAME" = "acidslide-v1.0.0" + uv run python ../benchmark/validate_corpus.py --release + + launch: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install launch media inspector + run: | + sudo apt-get update + sudo apt-get install --yes ffmpeg + - run: node launch/verify-launch.mjs + + container: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - run: docker build --platform linux/amd64 --tag acidslide-ci acidslide-v1 + - name: Verify frozen runtime and font inventory + run: | + docker run --rm --platform linux/amd64 --network none acidslide-ci --version + docker run --rm --platform linux/amd64 --network none \ + --entrypoint /bin/sh acidslide-ci -ec ' + test "$(date -u +%Y-%m-%dT%H:%M:%SZ)" = "2025-01-01T00:00:00Z" + libreoffice --version | grep -F "LibreOffice 7.3.7.2" + pdftoppm -v 2>&1 | grep -F "22.02.0" + test "$(fc-list -f "%{file}\n" | sort -u | wc -l)" -eq 26 + ' + - name: Reference deck passes quarantine and ECMA-376 validation + run: | + output=$(docker run --rm --platform linux/amd64 --network none \ + --volume "$PWD/acidslide-v1/benchmark/deck/gold/acidslide-v1-gold.pptx:/input.pptx:ro" \ + acidslide-ci validate /input.pptx 2>&1) + grep -F "Quarantine passed" <<<"$output" + grep -F "ECMA-376 schema: valid" <<<"$output" + + service: + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: acidslide-v1/service + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v6 + with: + version: "0.8.4" + enable-cache: true + - run: uv sync --extra dev --locked + - run: uv run ruff check . + - run: uv run ruff format --check . + - run: uv run mypy acidslide_service tests + - run: uv run pytest --cov=acidslide_service --cov-report=term-missing --cov-fail-under=85 + - run: uv run pip-audit + + service-images: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Build canonical grader base + run: | + docker build --platform linux/amd64 --provenance=false \ + --tag acidslide/grader:1.0.0 acidslide-v1 + - name: Build API, worker, and quarantine images + run: | + docker build --platform linux/amd64 --provenance=false \ + --build-context schemas=acidslide-v1/schemas \ + --target api --tag acidslide/service-api:1.0.0 acidslide-v1/service + docker build --platform linux/amd64 --provenance=false \ + --build-context schemas=acidslide-v1/schemas \ + --target worker --tag acidslide/service-worker:1.0.0 acidslide-v1/service + docker build --platform linux/amd64 --provenance=false \ + --build-context schemas=acidslide-v1/schemas \ + --target quarantine-job --tag acidslide/quarantine:1.0.0 acidslide-v1/service diff --git a/.gitignore b/.gitignore index 08828cc..cbbade6 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ htmlcov/ # Large reference docs (download separately) ECMA/ +.gstack/ diff --git a/ACIDSLIDE_OPENSPEC.md b/ACIDSLIDE_OPENSPEC.md index 91ea72a..f1a89ef 100644 --- a/ACIDSLIDE_OPENSPEC.md +++ b/ACIDSLIDE_OPENSPEC.md @@ -1,22 +1,28 @@ # AcidSlide v1 OpenSpec -Status: Final (ECMA-376 architecture — 11 adversarial rounds, Claude Opus 4.6 + gpt-5.4) +Status: Draft — adversarial review remediation in progress; not freeze-ready Scope: Public benchmark, automated grading suite, and hosted evaluation service for slide generation fidelity Primary artifact: A fully public, machine-graded PowerPoint benchmark inspired by the ACID browser tests ## 1. Summary -`AcidSlide` is a benchmark for evaluating whether a model can generate a `.pptx` deck from natural-language prompt inputs while preserving both: +`AcidSlide` is a benchmark for grading whether a submitted `.pptx` artifact conforms to natural-language prompt requirements while preserving both: - rendered visual fidelity under a fixed reference renderer (LibreOffice Impress headless) - user-visible structural fidelity inside the PowerPoint deck -The benchmark tests two capabilities in combination: +The artifact test exercises two properties in combination: -1. **Prompt interpretation**: can the model translate natural-language slide descriptions into correct PowerPoint constructs? -2. **Output fidelity**: does the generated deck match the gold standard visually and structurally? +1. **Prompt conformance**: does the artifact encode the requested PowerPoint constructs? +2. **Output fidelity**: does the artifact match the published reference images visually and satisfy + the frozen item-scoped structural assertions? -Reference images are provided as supplementary guidance, not as the sole source of truth. The natural-language prompt/spec is the primary input; the reference image resolves visual ambiguity where the prompt is intentionally underspecified. +V1 may record a submitter's attested model attribution, but artifact-only grading cannot establish +that the named model performed the generation. Model capability claims require v2 Execution Mode. + +Reference images supplement the natural-language prompt and resolve visual details the prompt leaves +underspecified. They are authoritative only for assertions explicitly marked +`provenance.kind: reference_image`; they never create structural requirements from gold OOXML. The benchmark is intentionally gameable in v1. The goal is not secrecy. The goal is to create a brutal, public, tunable target that forces frontier models to get meaningfully better at producing real slides instead of image-backed fakes. @@ -30,11 +36,48 @@ Each tier is scored independently. A submission targets a specific tier and is g `AcidSlide` is available in two modes: -- **Local mode**: download the benchmark package, run the grader locally using Docker (Linux/macOS/Windows). Scores are self-reported and unverified. -- **Hosted mode**: submit via API to the AcidSlide service, which grades in a controlled Linux Docker environment and publishes verified scores to the leaderboard. Only hosted-mode scores appear on the official leaderboard. +- **Local mode**: download the benchmark package and run the grader locally using Docker (Linux/macOS/Windows). Scores are self-reported and are not official leaderboard results. +- **Hosted mode**: submit via API to the AcidSlide service, which grades in the canonical controlled environment and publishes **grading-verified** scores to the official leaderboard. Submissions are graded only from the final submitted `.pptx`. No tool traces, reasoning logs, or intermediate artifacts affect the score. +### 1.1 Verification terminology + +AcidSlide distinguishes three claims that MUST NOT be collapsed into a single unlabeled +"verified" badge: + +- **Grading-verified**: the uploaded artifact was quarantined, rendered, inspected, and scored by + the official hosted service in an attested canonical environment. Every official v1 + leaderboard score has this property. +- **Generation-attested**: the submitter disclosed the generation method, intervention, post- + processing, and external-resource use. These fields are self-reported in v1. +- **Generation-verified**: the service controlled the generation execution itself. This is out of + scope for v1 and reserved for v2 Execution Mode. + +Throughout this specification, an unqualified "verified score" means **grading-verified**. The v1 +UI and API MUST label generation claims as attested and MUST NOT imply that v1 verifies model +identity, generation method, absence of human intervention, or generation-time network behavior. + +AcidSlide v1 verifies **artifact conformance only**. Every public submission, campaign, robustness, +and leaderboard result MUST carry the exact label +`grading-verified artifact score; generation-attested`. The service, API, documentation, and UI +MUST NOT state or imply that a named model generated, passed, or independently reproduced the +benchmark. Model and generation fields are attribution metadata supplied by the submitter. + +Every normative report also carries `grading_mode: local | hosted`. A local submission report uses +the exact label `local artifact score; self-reported`, is permanently `eligible: false`, has +`campaign_contribution: 0.0`, null hosted identity/campaign/slot fields, and is never published by the +leaderboard service even when all artifact checks pass. Its `disqualification_state` is +`non_official_local` with reason `local_mode`, distinguishing publication ineligibility from an +artifact defect. Only `grading_mode: hosted` submission reports may use the public v1 verification +label or become eligible. + +Because the gold artifact is public, the release manifest publishes both its byte SHA-256 and a +`canonical_package_hash_v1` computed by the normative §18.4.2 profile. A submission matching either +hash is completed-ineligible with `gold_artifact_copy` +and is not leaderboard-eligible. This duplicate guard does not verify generation and cannot prevent +a submitter from making a semantically inert change to the public gold. + ## 2. Product Principles ### 2.1 Core principles @@ -42,18 +85,21 @@ Submissions are graded only from the final submitted `.pptx`. No tool traces, re - Public by default: gold deck, prompts/specs, assets, checklist items, and grader logic are all public in v1. - Deterministic by design: rendering, fonts, assets, slide size, and grading environment are fixed. - Native slides only: a visually correct screenshot hack is a failure. -- Machine-graded only: no human review path exists in the benchmark contract. +- Machine-graded only: no human judgment may change an individual score. Administrative dispute + review may reproduce a run or identify a grader defect, but any score-affecting correction must + follow the versioning policy and must never mutate an immutable run record in place. - User-visible equivalence: ignore unstable non-visible identifiers, but require equivalent visible and structural fidelity. - Single benchmark deck first: keep v1 operationally simple and hard enough to matter. - Progressive difficulty: Level 1/2/3 tiers track industry progress over time. -- Prompt-first evaluation: the natural-language prompt is the primary input; reference images are supplementary. +- Prompt-first evaluation: prompt-derived structural requirements are frozen before gold; published + reference images later become authoritative only for explicitly provenance-linked visual assertions. - Standards-based: targets ECMA-376 (Office Open XML), not any single renderer. Like the ACID browser tests targeted W3C standards, not one browser. - Cross-platform by design: the entire benchmark runs on Linux in Docker. No Windows or Microsoft Office dependency. - Prompts are designed artifacts: prompts are authored and validated independently before the gold deck, not reverse-engineered from it. ### 2.2 What this benchmark is testing -The benchmark tests whether a model can: +The intended generation task asks a generator to create an artifact that demonstrates: - interpret natural-language prompt/spec input as the primary directive - use reference images as supplementary visual guidance where prompts are underspecified @@ -73,11 +119,11 @@ The benchmark tests whether a model can: - SmartArt - non-PowerPoint submission formats - strict OOXML schema validity as a goal in itself -- whether the model is useful for ordinary business decks (see §2.4) +- whether the attributed generator is useful for ordinary business decks (see §2.4) ### 2.4 External validity disclaimer -AcidSlide v1 is a ceiling test using deliberately hostile torture slides, not a measure of general slide-generation utility. A model that fails AcidSlide may still be useful in production. A model that passes AcidSlide by overfitting to the public benchmark may still be poor at novel slide generation. Realistic multi-slide story decks are planned for v2. +AcidSlide v1 is a ceiling test using deliberately hostile torture slides, not a measure of general slide-generation utility. A low artifact score does not prove the attributed generator is useless in production. A high artifact score—especially on a public gold—does not prove the attributed generator can handle novel slide generation. Realistic multi-slide story decks and generation-verified execution are planned for v2. ## 3. Locked v1 Decisions @@ -94,7 +140,9 @@ The following product decisions are fixed for v1: - Grader visibility: fully public - Scoring model: weighted checklist items with severity tiers and an aggregate fidelity score - Target standard: ECMA-376 5th Edition (Office Open XML) — the `.pptx` format is PresentationML as defined in ECMA-376 Part 1 -- Structural grading: ECMA-376 schema validation (RELAX NG / XSD) plus semantic equivalence comparison against gold structure +- Structural grading: ECMA-376 Part 1 Transitional XSD validation plus item-scoped assertion + evaluation against the content-addressed MCE-resolved OOXML package; gold structure is a control + fixture, not an oracle - Visual grading: perceptual similarity check under a fixed reference renderer export, with exact pixel match as a reported stretch metric - Reference renderer: LibreOffice Impress headless (pinned version, Docker image) for official scoring; PowerPoint fidelity reported as optional bonus score (not required); Aspose.Slides may be evaluated as a higher-fidelity alternative in future versions - Runtime: Linux Docker container with pinned LibreOffice version — no Windows or Microsoft Office dependency @@ -111,19 +159,46 @@ The following product decisions are fixed for v1: ### 4.1 Task definition -For each slide, the model receives: +For the intended task, a generator receives: - a deck-level prompt describing global design system and cross-slide consistency expectations - a per-slide natural-language prompt/spec (the primary input) - a reference image exported from the gold deck (supplementary visual guidance) - a list of allowed external assets, including mirrored local copies and fixed URLs -The model must produce a PowerPoint deck that: +The graded PowerPoint artifact must: + +- satisfy every applicable frozen scored assertion derived from the published task inputs +- render with high visual fidelity to the published reference images under the reference renderer +- use native PowerPoint constructs where the prompt/spec requires them +- achieve the structural semantics required by the item-scoped assertion inventory + +Every scored assertion has exactly one authoritative provenance kind: + +- `prompt`: an atomic requirement transcribed from the deck or slide prompt before gold authoring +- `reference_image`: a visual assertion located by reference-image hash plus slide/region coordinates +- `asset_manifest`: an asset identity, licensing, or allowed-usage assertion + +The provenance kind is schema-constrained to the property being asserted. The compatibility matrix +is normative and fail-closed: + +| Provenance kind | May prove | MUST NOT prove | +|---|---|---| +| `prompt` | Any atomic visual, textual, structural, editability, native-object, relationship, master/layout, field, or asset-usage requirement stated by the cited prompt bytes | A requirement absent from the cited prompt locator | +| `reference_image` | Only properties directly observable in the cited pixels: visible glyph appearance, color, geometry, crop, overlap, z-order as rendered, spacing, and other rendered appearance | Exact Unicode/text semantics; native chart/table/field/placeholder type; editability; grouping; master/layout inheritance; theme semantics; relationship targets; hidden/off-canvas content; source font identity where pixels do not distinguish it; any other OOXML structure | +| `asset_manifest` | Asset identity, exact allowed bytes/hash, media type, intrinsic pixel dimensions, license, canonical URL, and explicitly declared allowed/required use | Placement/rendered dimensions, crop, z-order, visual composition, text, editability, native object type, master/layout/theme semantics, or any property not present in the cited manifest entry | -- correctly interprets the natural-language prompt -- renders with high visual fidelity to the gold deck under the reference renderer (LibreOffice) -- uses native PowerPoint constructs where the prompt/spec requires them -- achieves semantic structural equivalence with the gold deck +A `reference_image` assertion therefore uses `source_of_truth: render`; an +`asset_manifest` assertion may use OOXML inspection only to prove embedded-media identity or declared +usage. Any assertion whose kind, source of truth, verification method, or expectation falls outside +this matrix is schema-invalid and prevents the assertion inventory and release from freezing. A +reviewer cannot waive the matrix. If one property needs evidence from two kinds, it is split into two +independently scored atomic assertions; provenance is never expressed as an unordered union. + +The gold `.pptx` package and extracted gold scene graph are control fixtures, never requirement +sources. They cannot create, waive, or strengthen a scored assertion. A gold-derived expected value is +scoreable only after an independent reviewer traces it to one of the three published provenance kinds +above and freezes that assertion before release. ### 4.2 Official success criterion @@ -161,17 +236,23 @@ The following are automatic failures for any affected slide: ### 4.4 Repair behavior -If LibreOffice repairs or silently corrects a malformed submission on open: +V1 detects only observable repair signals: a LibreOffice recovery diagnostic, a renderer warning +classified in the frozen release manifest, a non-zero renderer exit, or a saved recovery artifact. +V1 does **not** claim to detect every in-memory or silent LibreOffice normalization. + +When an observable repair signal occurs: -- **Visual scoring** (Stage 2) uses the rendered state (what LibreOffice actually renders after any auto-correction) -- **Structural scoring** (Stage 3) uses the original uploaded .pptx (what the model actually generated) -- **Schema validation** (Stage 0.5) catches structural issues before rendering +- **Visual scoring** (Stage 2) renders the content-addressed MCE-resolved package +- **Structural scoring** (Stage 3) inspects that same MCE-resolved package +- **Schema validation** (Stage 0.5) validates that same package before rendering +- the original upload is retained only for provenance, quarantine evidence, and duplicate detection -A submission that triggers LibreOffice document recovery is flagged with `repair_triggered: true`, and `deck_passed` is set to `false` (a repaired deck cannot achieve a perfect pass). The repair event is logged in the report. +A submission that triggers an observable repair signal is flagged with `repair_triggered: true`, and `deck_passed` is set to `false` (a repaired deck cannot achieve a perfect pass). The event and matched signal are logged in the report. `schema_validation_performed == false`, `schema_valid == false`, an unclassified renderer warning, or an observable repair signal also forces `verification_complete == false`, `eligible == false`, and `deck_passed == false`. ## 5. Scope of Structural Fidelity -Structural fidelity in v1 means semantic equivalence in user-visible object structure, not literal isomorphism with the gold deck's internal representation. +Structural fidelity in v1 means satisfaction of the frozen item-scoped structural assertions, not +literal isomorphism with the gold deck's internal representation. ### 5.1 Structural properties that must match (semantically) @@ -180,9 +261,9 @@ Structural fidelity in v1 means semantic equivalence in user-visible object stru - layout/master usage where required by the prompt - placeholder usage and placeholder type where required by the prompt - object type (a table must be a table, a chart must be a chart) -- grouping structure (objects that are grouped in gold must be grouped in submission, but internal group nesting depth may differ if the visual and logical result is equivalent) +- grouping structure at the depth required by the prompt-derived assertion; nesting may vary only for items whose declared equivalence policy permits it - z-order (user-visible stacking order must match) -- object count (within a tolerance of ±0 for required objects; decorative objects may vary if visually equivalent) +- object count where an assertion requires it (within a tolerance of ±0 for required objects; optional decorative objects may vary only when the item declares a bounded optional count and deterministic matching rule) - text content (exact Unicode match) - text editability - script and directionality behavior @@ -190,20 +271,22 @@ Structural fidelity in v1 means semantic equivalence in user-visible object stru - chart presence, chart object type, and visible data representation where required - table presence and table object type where required - native field usage where required by the prompt -- geometry and placement (within defined tolerance) -- crop behavior -- overlap relationships -- on-canvas and intentional off-canvas placement +- geometry and placement where constrained by a prompt- or reference-image-sourced assertion (within defined tolerance) +- crop behavior where constrained by a prompt- or reference-image-sourced assertion +- overlap relationships where constrained by an assertion +- on-canvas and intentional off-canvas placement where constrained by an assertion - theme/master-driven versus per-slide override behavior where required by the prompt ### 5.2 Semantic equivalence rules -The comparator recognizes that multiple valid PowerPoint implementations can produce the same user-visible result. The following are treated as equivalent: +The comparator recognizes that multiple valid PowerPoint implementations can produce the same user-visible result. Equivalence is item-scoped, not global: every checklist item MUST declare the property it constrains and its matching/equivalence policy. A permissive policy never overrides an explicit prompt requirement. Subject to that declaration, the following may be treated as equivalent: -- Different internal group nesting that produces the same visual hierarchy and z-order +- Different internal group nesting that produces the same visual hierarchy and z-order, except when group depth or membership is the tested property - Different XML serialization order that produces the same rendered output -- Different shape implementation (e.g., freeform vs. preset geometry) that produces visually identical geometry within tolerance -- Different color specification methods (theme reference vs. explicit RGB) that produce the same rendered color +- Different shape implementation (e.g., freeform vs. preset geometry) that produces visually identical geometry within tolerance, except when a native/preset shape type is required +- Different color specification methods (theme reference vs. explicit RGB) that produce the same rendered color, except when theme inheritance or local override behavior is required + +Unmatched objects fail unless the applicable item marks them optional, supplies a bounded count, and defines deterministic matcher tie-break rules. The comparator MUST NOT silently choose the pairing that maximizes score. The comparator does NOT treat the following as equivalent: @@ -259,14 +342,33 @@ Includes Level 2 slides plus 8 additional slides testing: ### 6.2 Tier scoring -Each tier is scored independently. A model's profile includes: +Each tier is scored independently. A leaderboard attribution profile may include separately completed +campaign results for: - Level 1 score (foundation) - Level 2 score (intermediate) - Level 3 score (full torture) - Aggregate weighted score -A model may submit for any tier independently. +A submitter may open a separately bound campaign for any tier. + +The inclusion algorithm is exact. Let `S1 = {1..5}`, `S2 = {1..12}`, and `S3 = {1..20}`. For a +campaign targeting tier `T`, the evaluator constructs one immutable ordered item set before reading +submission results: + +1. include an item only when `item.tier <= T`; +2. for `scope: slide`, additionally require `item.slide in ST` and require the checklist validator to + prove that `item.tier` equals the minimum tier containing that slide; +3. for `scope: deck`, evaluate the item against exactly `ST`; any resolved affected-slide list is + intersected with `ST` before propagation; +4. order included items by UTF-8 byte order of `item.id`, reject duplicate IDs/assertion IDs, and + compute totals only from this frozen set; and +5. include informational items in diagnostics and counts explicitly labeled informational, but omit + their zero weights from the score denominator and perfect-pass predicate. + +No runtime object match, gold content, failure outcome, or optional field may change item +applicability. The three tier-item-set hashes are published in the scoring manifest and tested against +the complete checklist bundle. ## 7. Proposed Benchmark Package @@ -278,6 +380,7 @@ acidslide-v1/ SPEC.md VERSION CHANGELOG.md + RELEASE_KEYS.json Dockerfile # canonical grading environment docker-compose.yaml environment/ @@ -287,11 +390,47 @@ acidslide-v1/ drift-canary.md schemas/ ecma-376/ # ECMA-376 5th Edition schemas - relaxng-transitional/ xsd-transitional/ checklist-item.schema.json report.schema.json + report-semantic-projection.schema.json + submission-status.schema.json + prompt-requirements.schema.json + scored-assertion.schema.json + scored-assertion-inventory.schema.json + scoring-manifest.schema.json + release-index.schema.json + release-index-chain.schema.json + release-keys.schema.json + runtime-freeze-input.schema.json + environment-attestation.schema.json + grader-source-tree-profile.schema.json + grader-source-tree-profile-v1.json + grader-source-tree-manifest.schema.json + generation-profile.schema.json + control-handoff.schema.json + gold-evidence.schema.json + export-determinism-evidence.schema.json + scene-graph.schema.json + baseline-evidence.schema.json + mce-profile.schema.json + mce-profile-v1.json + schema-root-map.schema.json + schema-root-map-v1.json + canonical-package-hash-profile.schema.json + canonical-package-hash-v1.json + package-hash-fixture.schema.json benchmark/ + scoring-manifest.json + release-index.json + release-index-chain.json # required above sequence 1; optional for legacy genesis + grader-source-tree-manifest.json + environment-attestation.json + gold-evidence.json + export-determinism-evidence.json + requirements/ + prompt-requirements.json + scored-assertion-inventory.json tiers/ level-1/ slides.json # which slides comprise this tier @@ -335,6 +474,16 @@ acidslide-v1/ slide-02.yaml ... fixtures/ + index.json + positive/ + single-fault-negative/ + mutations/ + mce/ + gold-duplicate/ + quarantine-handoff/ + verdict-replay/ + opc/ + report-semantic-projection/ expected-scenegraphs/ slide-01.json ... @@ -375,26 +524,35 @@ V1 uses: - one deck-level prompt - one prompt/spec per slide (the primary input) -- optional paraphrased prompt variants that all target the same gold deck +- optional paraphrased prompt variants that all target the same published reference images, asset + manifest, and assertion semantics Prompt design principles: - no intentional ambiguity in canonical prompts - no hidden constraints - no attempt to trap the model on underspecified details -- prompts are derived from the gold deck but reviewed independently for completeness +- canonical prompts are authored and independently convergence-tested before the gold deck; the + gold deck is then authored from those frozen prompts -The reference image is supplementary visual guidance. Where the prompt is specific, the prompt takes precedence. Where the prompt is intentionally underspecified (e.g., exact color shade), the reference image resolves the ambiguity. +The reference image is a published task input and may resolve visual details that the prompt leaves +unspecified (for example an exact color shade). The prompt takes precedence for any conflict. The +scored-assertion inventory records whether each expectation comes from `prompt`, `reference_image`, +or `asset_manifest`, including an exact prompt citation or reference-image hash and region. Gold OOXML +is never a fourth provenance kind. ### 8.2 Prompt robustness protocol Paraphrased variants are scored as follows: - The canonical prompt set is the official benchmark input -- Each paraphrased variant set is scored independently using the same gold deck and checklist -- A model's **robustness score** is computed **per tier**: for each tier, it is the minimum of each variant's best official score (across all submissions) for all standard variants (canonical + paraphrase-a + paraphrase-b) -- To claim an official robustness score for a tier, **all standard variants must be submitted for that tier**. Partial variant sets do not produce a robustness score. -- The leaderboard displays the canonical score (always) and the robustness score (only when all variants are submitted) +- Each prompt variant is a separate single-tier campaign scored against the same published reference + images, asset manifest, and scored-assertion inventory +- A `robustness_group` score is computed per tier as the minimum official mean of its exactly three + child campaigns (`canonical`, `paraphrase-a`, `paraphrase-b`) in one scoring cohort and window +- A group produces an official robustness score only after all three child campaigns complete their + three slots. Partial groups remain provisional and unranked +- The leaderboard displays each canonical campaign score and the parent robustness score when complete - Mean and standard deviation across variants are also displayed when available ### 8.3 Asset model @@ -407,12 +565,11 @@ Each explicitly allowed external image must have: - content hash (SHA-256) - usage constraints if needed -The grader verifies embedded media using a two-tier hash model: - -- **Primary hash**: SHA-256 of the original asset file from the manifest. This is checked first. -- **Accepted recompression hashes**: PowerPoint may internally recompress images (e.g., JPEG re-encoding at its default quality). For each asset in the manifest, the benchmark package pre-computes and stores a set of known recompression hashes by opening the gold deck, extracting the media part, and hashing it. These are published alongside the primary hash. - -An embedded media part passes the asset check if its hash matches either the primary hash or any accepted recompression hash for that asset. No other variants are accepted. +V1 accepts only the primary SHA-256 bytes published in the manifest. Gold-derived recompression +hashes are not accepted because they privilege one authoring path and make the gold define its own +oracle. A future MAJOR version may publish a deterministic, versioned encoder matrix and accept its +precomputed outputs. PowerPoint or another tool that recompresses an asset must be configured to +preserve the manifest bytes for v1. ## 9. Canonical Runtime @@ -430,24 +587,17 @@ LibreOffice Impress headless is the reference renderer because: - it runs on Linux in Docker (cross-platform, CI/CD friendly) - it is deterministic within a pinned version + pinned font set - it natively reads ECMA-376 PresentationML (`.pptx`) -- it supports headless batch export to PNG +- it supports headless batch export to PDF for rasterization by the pinned Poppler build - it has no COM automation fragility, no modal dialogs, no GUI dependency -ECMA-376 schema validation (using the RELAX NG and XSD schemas from the standard) provides structural validation that is independent of any renderer. +ECMA-376 schema validation using the bundled Part 1 Transitional XSD schema set provides structural validation that is independent of any renderer. RELAX NG validation is out of scope for v1; publishing two nominally normative schema paths without identical processing semantics would make conformance ambiguous. ### 9.3 Rendering fidelity expectations -LibreOffice rendering differs from PowerPoint in known ways: - -| Feature | LibreOffice Fidelity | Notes | -|---------|---------------------|-------| -| Text and shapes | ~90%+ | With metric-compatible fonts installed | -| Standard charts | ~80-85% | Minor layout differences | -| Tables | ~85-90% | Minor spacing differences | -| Images/media | ~95%+ | Embedded images render correctly | -| SmartArt | Poor | Intentionally excluded from v1 benchmark (§2.3) | - -The v1 benchmark deliberately avoids features where LibreOffice fidelity is poor (SmartArt, animations, 3D effects). +LibreOffice differs from PowerPoint, but v1 does not publish unmeasured fidelity percentages. The +only normative visual expectation is conformance to the frozen canonical LibreOffice export. Any +renderer comparison is a dated, descriptive experiment with its corpus and method published. V1 +excludes SmartArt, animations, and 3D effects. ### 9.3.1 Renderer-limited features @@ -462,43 +612,203 @@ This split ensures models get credit for producing correct OOXML structures even Before grading is enabled, the benchmark must freeze: -- Docker base image (e.g., `ubuntu:22.04`) +- one official platform (`linux/amd64`) and an OCI image digest, including a digest-pinned base image - LibreOffice version (exact build string, e.g., `libreoffice-7.6.4.1`) -- export resolution +- Poppler, Pillow, NumPy, scikit-image, lxml, Python, and grader versions +- exact export commands, flags, color mode, PNG encoding parameters, and export resolution +- a fresh isolated LibreOffice user profile for every export; command templates serialize its + runtime `file://` URI as the literal token `file://` - slide size -- font installation set (libre metric-compatible fonts) -- locale settings (`en-US.UTF-8`) +- font installation set and file hashes (libre metric-compatible fonts) +- a frozen Fontconfig configuration whose discovered font-file set equals the font manifest exactly; + extra dependency, host, or fallback font files fail the environment build +- locale settings (`en_US.UTF-8`) - timezone (`UTC`) - reference datetime for date/time fields: `2025-01-01T00:00:00Z` +- `libfaketime` build/version and wrapper configuration used to supply that datetime to LibreOffice + and every grader subprocess +- the final SSIM algorithm profile and numeric threshold + +The release publishes a content-addressed scoring manifest containing every value above plus the +benchmark, prompt, checklist, schema, asset, font, MCE-profile, gold, and 100-run export-determinism +evidence hashes. The scoring-manifest hash is present in every report and defines the comparison +cohort. + +`scoring-manifest.json` is serialized as RFC 8785 canonical JSON and intentionally contains neither +its own hash nor `scoring_cohort_id`; this avoids a self-hash cycle. A separately signed +`release-index.json` records the manifest hash, the three-field cohort descriptor below, its derived +ID, benchmark version, single release state, chain metadata, and release signature. Consumers recompute both hashes +before trusting the index. The signature is Ed25519 over RFC 8785 canonical JSON with the `signatures` +field omitted; each signature object contains `key_id` and base64 signature bytes. Authorized public +keys and validity windows live in version-controlled `RELEASE_KEYS.json`, and a release requires at +least one non-revoked key valid at `issued_at` and `effective_at`. + +For API and storage interoperability, `scoring_cohort_id` is +`sha256:`, where `cohort_descriptor` is exactly: -### 9.5 Export contract +```json +{ + "schema_version": "1.0", + "scoring_manifest_sha256": "sha256:...", + "grader_source_tree_sha256": "sha256:...", + "environment_attestation_sha256": "sha256:..." +} +``` -The official export path: +Every report and public row carries the ID and all three component hashes. Comparability and +aggregation require exact equality of all four fields; the service recomputes the ID and rejects a +mismatch. A benchmark version string alone never defines a scoring cohort. + +#### 9.4.1 Grader source-tree construction profile + +The release publishes the algorithm `schemas/grader-source-tree-profile-v1.json`, validated by +`schemas/grader-source-tree-profile.schema.json`, and a release-specific +`grader-source-tree-manifest.json`, validated by +`schemas/grader-source-tree-manifest.schema.json`. `grader_source_tree_sha256` is the SHA-256 of RFC +8785 canonical JSON for exactly the release manifest (the manifest contains no self-hash). It binds +the profile ID/hash and contains: + +- `schema_version`, `manifest_id`, `source_tree_profile_sha256`, and the fixed root + `acidslide-v1/grader`; +- one entry for every release source, resource, lock, build, and test file under that root, with a + root-relative NFC-normalized POSIX path, byte length, exact-byte SHA-256, and executable boolean; +- entries sorted by Unicode code-point order of `path`, with duplicate, case-fold-colliding, + non-NFC, absolute, empty-segment, `.`/`..`, backslash, NUL, symlink, device, socket, and hard-link + entries rejected; and +- no implicit ignore rules. Generated caches/build output are absent only because the frozen profile + enumerates the complete allowed path set; an extra or missing filesystem entry fails verification. + +File contents are hashed byte-for-byte; line endings, encoding, modes represented by the executable +flag, and empty files are not normalized away. A source archive is accepted only after reconstructing +and matching this exact inventory. The scoring manifest binds the profile hash, manifest hash, and +resulting tree identity. The repository does not create a release manifest until the source tree is +actually frozen. + +The frozen package carries the reconstruction input as +`benchmark/grader-source-tree.tar`. It is a tar archive whose regular-file members are rooted at +`acidslide-v1/grader/`; container ordering, timestamps, owners, and compression are not identities. +The verifier rejects absolute/dot/non-NFC/case-colliding paths, links, special files, duplicate or +unmanifested members, missing members, byte-length/hash drift, and execute-bit drift before accepting +the signed cohort. A repository checkout may instead supply the exact grader root directory. The +runtime must reconstruct and match `benchmark/grader-source-tree-manifest.json`, its profile hash, +the scoring-manifest artifact bindings, and the signed cohort's `grader_source_tree_sha256` before +activating a release. The archive and final manifest remain absent until the source tree is frozen. + +#### 9.4.2 Environment-attestation construction profile + +The environment payload validates against `schemas/environment-attestation.schema.json` and contains +no self-hash. It records the platform/architecture, OCI digest, exact build IDs and executable hashes +for LibreOffice/Poppler/Python and every scoring library, locale/timezone/reference clock, +`libfaketime`, export/PNG/SSIM profile hashes, Fontconfig configuration hash, sorted exact font-file +inventory, schema/MCE/package-hash profiles, grader source-tree hash, and canary identity. Unknown +properties fail validation. `environment_attestation_sha256` is +`sha256:`. + +The worker reconstructs the attestation from the running container rather than trusting submitted or +deployment metadata, validates it, recomputes its hash, and compares it with the active scoring +manifest before grading. Every report contains both the payload and digest; a missing field, +unexpected runtime/font, invalid schema, or digest mismatch makes verification incomplete. + +#### 9.4.3 Signed release-index chain and rollback protection + +Every release index belongs to the fixed `acidslide-v1-stable` channel and adds `sequence` (positive +integer), `previous_release_index_sha256` (`null` only for sequence 1), `issued_at`, and +`effective_at`. The Ed25519 signature covers these fields with the rest of the RFC 8785 canonical +index. `state` is one enum—`active`, `frozen`, or `superseded`—not simultaneous booleans. At most one +chain head may be active; a frozen/superseded index remains verifiable history but cannot accept new +campaigns. + +A consumer initializes from a configured trusted genesis or previously persisted chain head, then +accepts only a signature-valid index whose sequence is exactly the prior sequence plus one, whose +`previous_release_index_sha256` equals the exact JCS hash of that prior index, and whose +`effective_at >= issued_at`. It persists the highest accepted `(channel, sequence, hash)` before +activating the index. A lower sequence, same-sequence different hash, skipped sequence, unknown fork, +future-issued index outside the configured clock-skew bound, or rollback to an earlier active state +fails closed. Reinstalling a client or clearing cache does not authorize rollback; recovery requires +the trusted chain from genesis, not a mutable latest-index pointer. + +The frozen release package serializes that recovery chain as RFC 8785 canonical +`benchmark/release-index-chain.json`, validated by `schemas/release-index-chain.schema.json`. Its +`indexes` array contains every complete signed index from sequence 1 through the current head, and +its final object must be byte-for-byte equal to canonical `benchmark/release-index.json`. A legacy +sequence-1 genesis package may omit the chain file. A package above sequence 1 cannot bootstrap from +its own mutable contents: it requires a configured trusted-genesis hash or a durable previously +accepted head. The consumer stores the highest accepted channel, sequence, index hash, and genesis +hash outside cache storage before activating the head; cache deletion does not remove or reset this +state. + +#### 9.4.4 100-run export-determinism evidence + +The release publishes RFC 8785 canonical `benchmark/export-determinism-evidence.json`, validated by +`schemas/export-determinism-evidence.schema.json`. It contains no self-hash. The signed scoring +manifest binds `sha256:` as +`gold.export_determinism_evidence_sha256`. + +The evidence binds the exact environment-attestation hash; original and MCE-resolved gold hashes; +canonical-package identity/profile; canonical PDF and ordered page-1..20 PNG hashes; and the frozen +export and SSIM profile hashes. Run 1 is the canonical published PDF/PNG export and must match those +bound hashes exactly. A substituted environment, package, profile, PDF, or page export invalidates +the evidence. + +The payload contains exactly 100 ordered export runs, each with exactly 20 ordered pages, and every +unordered run pair in lexicographic `(run_a, run_b)` order. Therefore it contains exactly +`100 choose 2 = 4,950` run-pair records and `4,950 * 20 = 99,000` page-pair SSIM comparisons. For +every pair, the validator recomputes the pair minimum from its 20 pages; for every page, it recomputes +the minimum across all 4,950 run pairs; and it recomputes the global minimum across all 99,000 +comparisons. Stored counts and summaries are assertions, not trusted shortcuts. Missing, duplicate, +reordered, non-finite, or out-of-range records fail closed. + +Every recomputed per-page minimum and the recomputed global minimum must be at least `0.99999`. +Meeting only the aggregate minimum is insufficient. The release file is created only from the real +pinned-environment runs; the repository keeps the schema and validator without a placeholder or +synthetic evidence instance before that campaign completes. -- open presentation in LibreOffice Impress headless -- export all slides to PNG at **1920 × 1080 pixels** (16:9) +### 9.5 Export contract + +The one official export path is PPTX → PDF → PNG: + +- before export, require `/ppt/presentation.xml` `p:sldSz` to be exactly + `cx=12192000`, `cy=6858000` EMU; missing, alternate-orientation, or merely ratio-equivalent values + fail validation +- open the presentation in LibreOffice Impress headless and export PDF +- require exactly 5, 12, or 20 PDF pages according to the targeted campaign tier. LibreOffice + `7.3.7.2` converts the exact v1 EMU width through its 1/100-mm representation, so the frozen raw + page profile is `MediaBox [0 0 960.009448818898 540]` PostScript points—not an idealized `960 × + 540`. Parse PDF numbers as exact decimals and require those four values; `CropBox` must be absent or + exactly equal that MediaBox, and `Rotate` must be absent or numeric zero. This observed profile + stores coordinates as canonical decimal strings and is bound with its LibreOffice build in the + scoring manifest. A missing, extra, differently boxed, + cropped, rotated, or stretched page is an artifact export failure and is never inserted, removed, + resized, or tolerated by ratio alone +- rasterize every PDF page with the pinned `pdftoppm` at exactly **1920 × 1080 pixels** (16:9) +- convert to RGB and encode PNG using the pinned Pillow version and frozen encoder parameters - compare exported PNGs against gold exports using perceptual similarity (see §22) - the reference datetime for date/time fields is pinned to `2025-01-01T00:00:00Z` +- the canonical wrapper launches LibreOffice, Poppler, and grader subprocesses with the manifest- + pinned `libfaketime` preloaded, `FAKETIME=@2025-01-01 00:00:00`, + `FAKETIME_DONT_FAKE_MONOTONIC=1`, locale `en_US.UTF-8`, and timezone `UTC`; the clock conformance + fixture must render and extract the pinned date before a release may freeze Export command (reference): ```bash -libreoffice --headless --convert-to png \ - --outdir /output /input/submission.pptx +libreoffice --headless --convert-to pdf \ + --outdir /work /input/submission.pptx +pdftoppm -png -scale-to-x 1920 -scale-to-y 1080 \ + /work/submission.pdf /work/acidslide-render ``` -If individual slide export is not supported in the pinned version, the two-step path is used: -```bash -libreoffice --headless --convert-to pdf /input/submission.pptx -# Then split PDF to per-page PNGs at 1920×1080 -``` +Direct PNG export, an alternate rasterizer, a resize fallback, a second architecture, or any other +export path is a grading error. It never silently substitutes for the canonical path. ### 9.6 Environment drift detection The grading environment includes an automated drift canary: - re-grades the gold deck on a weekly schedule -- compares pixel output and structural extraction against stored baselines -- alerts if any slide's perceptual similarity drops below the fidelity threshold +- compares canonical PNG hashes, score-semantic-report hashes (§26.1.1), and structural extraction hashes against + stored baselines +- alerts and blocks grading if any canonical PNG or score-semantic projection byte changes, even when SSIM + remains above the pass threshold - alerts if any structural extraction result changes - blocks new grading runs until drift is investigated and resolved - logs all canary results with timestamps for audit @@ -511,7 +821,7 @@ The benchmark ships a Dockerfile that produces the canonical grading environment FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ - libreoffice-impress libreoffice-core \ + libreoffice-impress libreoffice-core poppler-utils libfaketime \ fonts-liberation fonts-noto fonts-noto-cjk \ fonts-crosextra-carlito fonts-crosextra-caladea \ python3 python3-pip \ @@ -524,15 +834,33 @@ USER grader WORKDIR /benchmark ``` -This image is the canonical grading environment. Third-party implementations must match its output on the published test fixtures. +The example is illustrative and intentionally not a release manifest. The Dockerfile is a build +recipe, not the frozen identity. The released `linux/amd64` OCI digest and +scoring manifest are canonical. Mutable base tags, moving APT indexes, and unversioned package +resolution are prohibited in a frozen release. Third-party implementations must match the released +conformance corpus byte-for-byte at the §26.1.1 score-semantic projection layer. + +Files whose contents bind the OCI digest (`environment-attestation.json`, +`scoring-manifest.json`, release indexes, determinism/gold evidence, baselines, and control +handoffs) are excluded from the environment-image build context to avoid an OCI-digest +self-reference. The worker mounts the exact signed release package read-only and sets +`ACIDSLIDE_BENCHMARK_DIR` to that mount only after its release chain, scoring-manifest hash, grader +source tree, and environment-attestation hash have verified. Rebuilding an image never copies +OCI-bearing release metadata into the image it identifies. + +The release image does not trust package names as font evidence. Its build enumerates `fc-list` under +the frozen `FONTCONFIG_FILE`, hashes every reachable font file, compares the exact set with +`benchmark/fonts/manifest.json`, and fails on any missing or extra file. The worker mounts no host +font directories or caches. ### 9.8 Optional PowerPoint fidelity score -For models targeting PowerPoint-specific rendering, an optional **PowerPoint fidelity score** may be computed by running the grader on a Windows machine with PowerPoint installed. This score: +For private diagnostic use, an optional **PowerPoint fidelity score** may be computed by running a +separate, non-official comparator on a Windows machine with PowerPoint installed. This score: -- is reported separately on the leaderboard (not part of the official fidelity_score) +- appears only in the submitter's local/private report and never on the official leaderboard - is not required for leaderboard participation -- uses the same checklist and SSIM threshold +- uses separately exported PowerPoint gold references and identifies its non-canonical environment - is only available for on-premise or self-hosted grading (not the hosted service) This allows teams with PowerPoint access to measure PowerPoint-specific fidelity while keeping the official benchmark cross-platform. @@ -543,16 +871,22 @@ This allows teams with PowerPoint access to measure PowerPoint-specific fidelity The benchmark score is represented as: -- `fidelity_score`: weighted aggregate (0.0 to 1.0) +- `fidelity_score`: weighted aggregate (0.0 to 1.0) when scoring completes, otherwise `null` only for + the completed diagnostic states in §11.1.1 +- `campaign_contribution`: targeted fidelity when eligible, otherwise exactly `0.0` - `passed_items`: count of passed checklist items - `total_items`: count of total checklist items -- `deck_passed`: boolean (true only if fidelity_score == 1.0 AND no anti-cheat flags AND no repair events) -- `eligible`: boolean (true if the submission is eligible for the leaderboard — not rejected by quarantine, not timed out) +- `deck_passed`: boolean (true only if fidelity_score == 1.0, `verification_complete == true`, `schema_validation_performed == true`, `schema_valid == true`, no score-affecting anti-cheat disposition was triggered, and no repair event occurred) +- `eligible`: boolean (true only for a hosted submission eligible for the leaderboard — all required stages performed, schema-valid, not rejected by quarantine, not timed out, not a gold duplicate, and no grading error; local/control reports are always false) +- `grading_mode`: `local | hosted`; local reports are always non-official/ineligible as §1.1 defines +- `verification_complete`: boolean that is true only when every required grader stage reports `performed == true` +- `scoring_completed`: boolean that is true when Stage 5 produced the complete targeted item set and + score, even if a later/parallel eligibility condition makes verification incomplete - per-slide item pass/fail breakdown with severity - deck-level item pass/fail breakdown with severity - per-tier scores (Level 1, Level 2, Level 3) — non-targeted tiers are serialized as `null` in JSON output; they are not omitted - efficiency metrics (see §10.4) -- `anti_cheat_flags`: array of triggered anti-cheat rules (empty if clean) +- `anti_cheat_flags`: array of triggered anti-cheat rules, each with `disposition: warning | zero_slide | zero_affected_slides | reject` - `repair_triggered`: boolean ### 10.2 Severity tiers @@ -566,7 +900,10 @@ Each checklist item has a severity tier that determines its weight in the aggreg The fidelity score is: `sum(passed_item_weights) / sum(all_item_weights)` -**Tier aggregation**: each tier's fidelity score is computed independently using only the items belonging to that tier. The **aggregate score** displayed on the leaderboard is the Level 3 fidelity score (since Level 3 includes all slides). For submissions targeting Level 1 or Level 2 only, the aggregate score equals that tier's score. +**Tier aggregation**: a submission targets exactly one tier and serializes exactly one non-null tier +score matching the immutable `campaign.tier`; other tier fields are `null`. Level 3 includes all 20 +slides but is not simultaneously a Level 1 or Level 2 submission. The **aggregate score** equals the +targeted tier score. The pass/fail item count is also reported for item-level analysis. @@ -581,6 +918,8 @@ Deck-level items are scored independently from slide-level items. A deck-level i However, **automatic-fail rules** (§4.3) are a separate mechanism from normal item scoring. When an automatic-fail rule triggers, it zeroes all items on the affected slide(s), regardless of whether the rule was triggered by a slide-level or deck-level condition. +Only `zero_slide`, `zero_affected_slides`, and `reject` anti-cheat dispositions affect `deck_passed`. A `warning` is diagnostic and does not change the score or pass state. + ### 10.4 Efficiency metrics Efficiency metrics are split into **verified** (measured by the service) and **attested** (self-reported by the submitter): @@ -617,40 +956,141 @@ This yields roughly 255 to 390 total checks. Severity distribution should target ### 11.1 Official scoring protocol -For non-deterministic generation systems: - -- the official leaderboard score is the **best score across all submissions** for a given `(model_id, model_version, benchmark_version, prompt_variant)` tuple -- all submission scores are recorded and visible on the leaderboard -- mean and standard deviation across submissions are also displayed -- hosted mode enforces a maximum of **3 submissions per (model_id, model_version, benchmark_version, prompt_variant) tuple** within a 7-day window -- a model claiming robustness (§8.2) must submit for all 3 standard variants, consuming up to 9 total submission slots (3 per variant) within the window - -### 11.5 Multi-window behavior - -The leaderboard uses **all-time** statistics for each `(model_id, model_version, benchmark_version, prompt_variant)` tuple. When a new 7-day window opens, new submissions are added to the cumulative record. The leaderboard's `best_score`, `mean_score`, `worst_score`, and `submission_count` reflect all submissions ever made (not just the latest window). The official score is the best across all submissions for that tuple. +An official reliability result is a precommitted seven-day **single-variant campaign** keyed by +`(submitter_id, model_key, model_revision_key, scoring_cohort_id, tier, prompt_variant, +assistance_class, generation_profile_sha256, window_id)`: + +- the service assigns an immutable `campaign_id` before the first artifact is uploaded +- the campaign contains the first **three accepted uploads that complete grading**; a graded but + ineligible artifact occupies a slot with campaign score `0.0`, while a service failure before a + report exists does not occupy a slot. A campaign with fewer than three completed slots is + displayed as provisional and is not ranked +- no reservation is accepted at or after derived `accepts_until` (§11.5.1); an earlier reservation + may finish afterward. Once every pre-cutoff reservation is terminal, a campaign with fewer than three occupied slots is + `closed-incomplete` and can never be ranked or refilled +- `official_score` is the arithmetic mean of the three `campaign_contribution` values; best, worst, + and standard deviation use those same values, while every constituent diagnostic fidelity (which + may be null) is displayed separately +- an all-time `record_score` may be displayed separately but MUST NOT be labeled official, + reliable, or reproducible +- each campaign has exactly one tier and one prompt variant and therefore contains exactly three + occupied grading slots when complete +- each campaign immutably precommits `assistance_class: unassisted | human-assisted` and a + `generation_profile_sha256`. The profile is RFC 8785 canonical JSON describing the generator/API + revision, generation strategy, toolchain, temperature/sampling configuration, and whether human + intervention or post-processing is permitted; unknown properties fail its published schema. The + profile contains no artifact, result, run seed, timestamp, or self-hash. Every slot must attest the + same profile hash and assistance class. An `unassisted` campaign requires + `profile.permissions.human_intervention_permitted: false` and every run's + `human_intervention: false`. `human_intervention: true` is compatible only with + `human-assisted`; `post_processing` is independently frozen in the generation profile and may + describe an automated toolchain. A declaration inconsistent with either campaign binding is a + completed-ineligible result, never silently reclassified after scoring +- a `robustness_group` is a parent resource that links exactly three child campaigns—`canonical`, + `paraphrase-a`, and `paraphrase-b`—with the same immutable submitter/model/revision, tier, + scoring cohort, assistance class, generation-profile hash, and seven-day window. It contains nine + run slots in total but is not itself a campaign +- all eligible and ineligible run summaries are append-only and public; a run cannot be withdrawn + after the score is known + +#### 11.1.1 Submission/report/slot terminal-state table + +For `grading_mode: hosted`, transport acceptance creates one reservation, but only an immutable grading or diagnostic report +occupies a campaign slot. These outcomes are exhaustive: + +| Condition | Submission terminal status | Report/public run row | Slot effect | Retry semantics | +|---|---|---|---|---| +| Security quarantine rejection before schema diagnostics (malware, encryption, ZIP bomb, forbidden active/external content) | `rejected` | none; only a private non-attacker-controlled audit record | release reservation | artifact is non-retryable; a new upload consumes normal quota | +| Signed handoff signature/expiry/binding/object/hash mismatch | `failed` with `quarantine_handoff_mismatch` | none | release reservation | same verdict is never retried; service must rerun quarantine and issue a new verdict or operator-remediate | +| Schema/OPC/MCE invalid artifact after safe diagnostics exist | `completed` | completed-ineligible diagnostic report and sanitized public run row | occupy at campaign score `0.0` | non-retryable for that artifact | +| Published gold byte/canonical duplicate | `completed` | completed-ineligible diagnostic report and sanitized public run row with duplicate outcome | occupy at campaign score `0.0` | non-retryable for that artifact | +| Observable repair, unclassified renderer warning, attestation/campaign mismatch, or score-affecting `reject` disposition after a report exists | `completed` | completed-ineligible report and public run row | occupy at campaign score `0.0` | non-retryable for that report | +| Artifact-deterministic LibreOffice open/export failure reproduced once in a fresh worker with the same resolved hash | `completed` | completed-ineligible diagnostic report and sanitized public run row | occupy at campaign score `0.0` | non-retryable for that artifact | +| Infrastructure renderer crash/timeout, queue loss, storage outage, or worker loss before any report commit, with no evidence the artifact deterministically caused it | `failed` | none | release reservation | retryable service failure; a retry uses a fresh quarantine verdict | +| Successful complete grading, eligible or score-reduced | `completed` | immutable report and public run row | occupy with fidelity score when eligible, otherwise `0.0` | immutable; never replaceable | + +The service distinguishes artifact-deterministic renderer failure from infrastructure failure by one +fresh-worker replay of the same resolved object after issuing a new quarantine verdict. Two identical +artifact-stage failures yield the diagnostic zero-slot result; disagreement is an infrastructure +failure and releases the reservation. No other retry is permitted in an official campaign. A report +commit and `reserved -> occupied` transition occur in one transaction; once either exists, release is +forbidden. `failed` and `rejected` responses contain no `result`; `completed` responses contain a +schema-valid result, even when ineligible. + +Every completed result has `campaign_contribution`. It equals the numeric targeted fidelity score +only when `eligible: true`; otherwise it is exactly `0.0`. When grading never reached a complete score +(schema/OPC invalidity, duplicate rejection, or artifact renderer failure), `fidelity_score` and all +tier score objects are JSON `null`, not fabricated zeros, and `scoring_completed` is false. A +completed-ineligible report produced +after scoring may retain its numeric diagnostic score, but that value is explicitly non-ranking and +does not change `campaign_contribution: 0.0`; in that case `scoring_completed` is true even though +`verification_complete`/`eligible` are false. ### 11.2 Seed handling -If a model accepts a random seed: - -- the submission metadata must include the seed used -- the same seed should produce the same output (if the model claims determinism) -- the grader does not verify determinism but records the seed for reproducibility analysis +Every submission metadata object, grade report, immutable run record, and public run row contains the +member `generation_seed`. Its value is either the exact provider-facing seed rendered as a UTF-8 +string (maximum 256 bytes, with no normalization) or JSON `null` when the generator exposes no seed. +An omitted member is contract-invalid. If a generator accepts a seed, `null` is not permitted; the +submitter records the seed actually used. The same seed should produce the same output when the model +claims determinism. V1 records but does not independently verify generation determinism, and the seed +never changes scoring or campaign identity. ### 11.3 Cherry-picking prevention -- All submissions within a scoring window are recorded, not just the best -- The leaderboard shows best, mean, and worst scores -- Withdrawing a submission after seeing its score is not permitted in hosted mode +- Campaign membership is fixed before grading begins and uses the first three accepted uploads that + produce a grading report. A graded-ineligible upload occupies a slot at `0.0`; a service failure + before any report exists does not occupy a slot. +- Aliasing a display label or creating a new free-text version cannot create a new quota identity. +- The leaderboard shows every run plus mean, best, worst, standard deviation, and attempt count. +- Withdrawing or replacing a run after seeing its score is not permitted. +- Completed campaigns remain historical cohorts. A new campaign never modifies an earlier result. ### 11.4 Model identity policy -- `model_id` is a free-text identifier chosen by the submitter (e.g., "gpt-4o", "claude-sonnet-4") -- `model_version` distinguishes versions (e.g., "2025-03-01", "v2.1") -- The 3-submission-per-window limit applies to the `(model_id, model_version, benchmark_version, prompt_variant)` tuple (consistent with §11.1) -- Submitters who change `model_version` to circumvent the limit are treated as separate entries on the leaderboard (which is the correct behavior — each version gets its own scores) -- The leaderboard has two views: (a) **summary view** groups entries by `model_id` and shows the best `model_version`'s score per model, and (b) **detail view** lists every `(model_id, model_version)` entry individually -- Maintainers may merge or relabel entries if aliasing is detected (e.g., same model submitted under different IDs) +- `submitter_id`, `model_key`, and `model_revision_key` are server-issued immutable identifiers. +- Free-text model names and versions are display metadata only and never participate in quota, + grouping, comparison, or campaign keys. +- A model revision payload is immutable from creation. A new revision requires a new server-issued + key and public revision note; creating one does not reset organization-level quotas. +- Public rows identify the submitting organization and whether any model-owner attribution is + owner-verified or submitter-attested. +- Maintainers may correct display labels, but immutable keys and historical run records never change. + +### 11.5 Multi-window behavior + +Campaigns are displayed by their exact scoring cohort and closing date. The default ranking uses the +most recent completed campaign within each complete selection key +`(submitter_id, model_key, model_revision_key, scoring_cohort_id, tier, prompt_variant, +assistance_class, generation_profile_sha256)` and within the last 30 days. The ordering is +`completed_at DESC, campaign_id ASC`; neither a different tier/variant nor an assisted/profile cohort +may replace another row. Older campaigns remain accessible as history and receive a `stale` label. +Scores from different scoring cohorts are never combined. The all-time record view is explicitly +descriptive and non-official. + +#### 11.5.1 UTC windows and campaign state + +Seven-day windows are half-open UTC intervals anchored at `2025-01-06T00:00:00Z`. For server receipt +time `t`, `k = floor((t - anchor) / 604800 seconds)`, `opens_at = anchor + k*604800`, and +`closes_at = opens_at + 604800`; `window_id` is the ASCII string +`utc7:`. The server uses its trusted clock. A reservation transaction +whose commit time is `>= accepts_until` is rejected even if its request began earlier. +`accepts_until = min(closes_at, cohort_freeze_effective_at)` when a signed release-index transition +freezes/supersedes the cohort, otherwise it equals `closes_at`; the service returns this derived field +and the index hash that caused any earlier cutoff. + +Campaign status is derived, never client-set: + +| State | Exact predicate | +|---|---| +| `open` | current time is before `accepts_until`, zero occupied slots, and zero live reservations | +| `provisional` | fewer than three occupied slots and at least one occupied or live pre-cutoff reservation; after cutoff it remains provisional only while a pre-cutoff reservation is nonterminal | +| `completed` | exactly three immutable report-producing slots are occupied | +| `closed-incomplete` | current time is at/after `accepts_until`, fewer than three slots are occupied, and no pre-cutoff reservation remains nonterminal | + +`completed` and `closed-incomplete` are terminal. A campaign cannot transition from either state back +to `open`/`provisional`, and a completed campaign cannot become stale by mutation; `stale` is a derived +display label relative to query time. ## 12. Checklist Specification Format @@ -660,12 +1100,20 @@ Schema: ```yaml schema_version: "1.0" -id: slide-07.native-table-required +lifecycle_state: frozen +id: slide-03.native-table-required scope: slide -slide: 7 -tier: 2 # minimum tier that includes this item (1, 2, or 3) — slide 7 is in Level 2 +slide: 3 +tier: 1 # minimum tier that includes this item (1, 2, or 3) — slide 3 is in Level 1 title: Native table required -description: Slide must contain a native OOXML table matching the gold slide. +description: Slide must contain the native OOXML table required by the frozen prompt oracle. +prompt_requirement_id: slide-03.prompt-r005 +assertion_id: slide-03.assert-native-table +provenance: + status: complete + kind: prompt # prompt | reference_image | asset_manifest + source_hash: sha256:... +locator: "prompts/variants/canonical/slide-03.md#L15" kind: structure severity: critical source_of_truth: ooxml # ooxml | render | both @@ -675,6 +1123,7 @@ source_of_truth: ooxml # ooxml | render | both verification: method: object_compare selector: table + matching_policy: exact_native_type_and_prompt_geometry expectation: exact_count: 1 required: true @@ -688,13 +1137,53 @@ failure_mode: automatic_fail_if: - grouped_lines_and_text_used_as_table - raster_image_used_as_table - propagation: zero_slide # zero_slide | zero_item | zero_affected_slides + propagation: zero_slide # zero_slide | zero_affected_slides + affected_slides: + status: complete + mode: current_slide # current_slide | explicit | named_selector + slides: [3] # required and sorted for current_slide/explicit + selector_id: null # content-addressed algorithm id for named_selector + selector_sha256: null # required hash for named_selector, otherwise null # zero_slide: zero all items on this slide - # zero_item: zero only this item (cannot be used with automatic_fail_if per §4.3) # zero_affected_slides: zero all items on all slides affected by a deck-level condition (for deck-scoped auto-fail rules) # automatic_fail_if rules MUST use zero_slide or zero_affected_slides +evidence: + status: complete + positive_fixture_ids: [fixture.slide-03.native-table.valid] + single_fault_negative_fixture_ids: [fixture.slide-03.native-table.flattened] + mutation_expectation_ids: [mutation.slide-03.flatten-native-table] ``` +`assertion_id`, `provenance`, and `evidence` are mandatory for every scored item. A +`prompt_requirement_id` is mandatory when `provenance.kind == prompt`; reference-image assertions +instead identify the immutable image hash and slide/region, and asset assertions identify the asset +manifest hash and asset ID. An extracted gold value without one of these provenance records is +diagnostic only. + +Authoring work may use `lifecycle_state: candidate` with explicit `status: pending` provenance, +evidence, or affected-slide metadata so the repository records omissions honestly. Such a document +is schema-valid candidate metadata but is never scoreable. A frozen scoring manifest accepts only +`lifecycle_state: frozen`; every frozen item must have complete matrix-compatible provenance, +complete nonempty evidence IDs that resolve to published fixtures/mutations, and complete +affected-slide rules for every automatic failure. The release validator rejects any candidate or +pending member across the complete bundle. + +At release, `benchmark/fixtures/index.json` is a closed +`acidslide-assertion-evidence-index-v1` projection. It binds the RFC 8785 review-projection SHA-256 +of the frozen assertion inventory and contains exactly one entry for every frozen assertion. Each +entry repeats that assertion's `assertion_id`, `checklist_item_id`, positive-fixture IDs, +single-fault-negative-fixture IDs, and mutation-expectation IDs byte-for-byte and in the same array +order. The release validator rejects duplicate, missing, substituted, or extra entries and any +projection hash mismatch. The index is an addressable cross-binding record, not evidence by itself; +it cannot upgrade candidate or generated-operator fixtures into independent assertion evidence. + +Every automatic-fail result emits the resolved, sorted `affected_slides`. `current_slide` resolves to +the slide being evaluated; `explicit` uses the frozen list; `named_selector` invokes an algorithm +whose identifier and content hash are in the scoring manifest. Scoring intersects that list with the +submitted campaign tier and zeroes only the intersection. An empty intersection is reported as a +warning for that targeted tier. The grader MUST NOT infer affected slides from whichever objects +happen to match most favorably. + A normative JSON Schema for checklist files will be published in `schemas/checklist-item.schema.json` (same location as the ECMA-376 schemas in the package layout, §7). Recommended top-level item categories: @@ -726,17 +1215,79 @@ The gold deck is authored using a **prompt-first** workflow. Prompts are designe Recommended workflow: 1. **Design prompts first.** Write natural-language slide specifications for each slide, covering all required constructs (tables, charts, masters, etc.). Prompts are the primary artifact — they must be unambiguous and complete. -2. **Validate prompts independently.** Have 2-3 skilled slide authors independently create slides from the prompts alone (no reference images), using LibreOffice Impress with the benchmark font set. **Convergence rule**: for each slide, score all independent implementations through the grader's structural comparison. If any two implementations achieve ≥ 80% structural similarity, the prompt is considered sufficiently specified. If no pair reaches 80%, the prompt is underspecified and must be revised. This process is documented per slide with results archived. -3. **Build the gold deck.** A skilled author builds the canonical gold deck in **LibreOffice Impress** (the reference renderer) using only the bundled libre fonts and approved assets. The gold deck must be authored in the same tool that will grade it to avoid serialization-dependent rendering differences. -4. **Validate ECMA-376 compliance.** Run the gold deck through RELAX NG schema validation against ECMA-376 Part 1 Transitional. Fix any schema violations. -5. **Export reference images.** Export gold slides using the canonical Docker environment (LibreOffice headless) to create the reference PNGs. -6. **Generate checklist items** from gold structure plus human review. -7. **Create baseline scores** (see §13.4). +2. **Freeze a prompt-derived requirements oracle before gold authoring.** Two independent reviewers transcribe every mandatory prompt requirement into atomic, machine-readable requirements. Each requirement identifies its prompt citation, severity, source of truth, and matching/equivalence policy. Disagreements are resolved against the prompt, never against a deck. +3. **Validate prompts independently without gold.** At least three blinded authors create each slide from the prompts alone (no gold or reference images), using LibreOffice Impress with the benchmark font set. Every mandatory assertion in the requirements oracle must pass for every implementation. Pairwise normalized scene-graph similarity is diagnostic only; it has no release threshold and cannot override a missed requirement. Any author disagreement or failed assertion requires prompt revision, oracle revision, and a fresh blinded round. +4. **Freeze the pre-gold assertion core.** Prompt-sourced assertions originate from the prompt-derived + oracle, and asset-identity/usage assertions originate from the independently authored asset + manifest. Each records an exact immutable source hash and locator before gold authoring. No + reference-image assertion exists yet. +5. **Build the gold deck.** A skilled author builds the canonical gold deck in **LibreOffice Impress** (the reference renderer) using only the bundled libre fonts and approved assets. The gold deck must be authored in the same tool that will grade it to avoid serialization-dependent rendering differences. +6. **Validate ECMA-376 compliance.** Run the gold deck through XSD validation against the bundled ECMA-376 Part 1 Transitional schema set. Apply Markup Compatibility and Extensibility preprocessing before XSD validation as defined in §15.1 Stage 0.5. Fix any schema violations. +7. **Export reference images.** Export gold slides using the one canonical export pipeline in the release manifest to create the reference PNGs. +8. **Freeze the complete scored-assertion inventory.** Independent reviewers may now add only visual + properties that satisfy the §4.1 `reference_image` matrix, each bound to exact reference-image + hash/slide/region. They review pixels and task inputs, not gold OOXML or the extracted gold scene + graph. Extractor-generated gold data may propose diagnostics, but cannot add, omit, waive, pass, or + become authority for a requirement. +9. **Validate the independent oracle.** Every scored property and anti-cheat rule must have at least one passing fixture, one single-fault failing fixture, and a published mutation expectation. Alternative valid implementations must exercise each declared semantic-equivalence policy. Gold-perfect is necessary but not sufficient; release requires the complete mutation matrix to match and every required mutant to be killed. +10. **Create baseline scores** (see §13.4). Baseline ranges are descriptive. A missed target range does not permit checklist or threshold tuning unless a diagnosed contract defect is published and the prompt/oracle freeze restarts. This prompt-first flow ensures that: - Prompts are tested artifacts, not afterthoughts - The benchmark measures prompt interpretation, not just reconstruction from reference images - Ambiguous prompts are caught before the gold deck is frozen +- A parser or gold extractor cannot certify itself by omitting a requirement + +#### 13.1.1 Single published gold identity + +The release publishes one `gold-evidence.json` that validates against +`schemas/gold-evidence.schema.json` and binds, at minimum: + +- the original authored gold byte hash/object identity; +- the exact `mce_resolved_package_sha256`/size produced by the frozen MCE, root-map, OPC, and XSD + pipeline; +- `canonical_package_hash_profile_sha256` and the resulting gold + `canonical_package_hash_v1`; +- schema/OPC validation evidence, gold scene-graph hash, each canonical PDF/PNG hash, page count and + page geometry, and the three signed reference-control report hashes; and +- the scoring manifest and release-index hashes under which those values were produced. + +There is exactly one resolved gold package per scoring manifest. XSD/OPC validation, reference PDF +and PNG export, scene-graph extraction, exact and canonical duplicate comparison, mutation-control +parentage, and all three tier reference controls MUST consume that same byte-identical resolved +package. A tool may retain the original authored package for provenance, but may not validate one +resolution, render another, extract a third, or compute duplicate hashes from the unresolved ZIP. A +digest or profile mismatch invalidates the complete gold evidence set and prevents release; no +component may be regenerated independently without issuing a new scoring manifest/cohort and rerunning +all dependent controls. + +#### 13.1.2 Reviewer approval projections + +Reviewer hashes bind the exact object reviewed and never hash an approval array containing their own +hashes. The prompt-oracle approval projection is RFC 8785 canonical JSON for exactly: + +```json +{ + "domain": "AcidSlide prompt requirements oracle review v1", + "oracle": "" +} +``` + +`reviewed_oracle_sha256` is the lowercase, unprefixed hexadecimal SHA-256 of those JCS bytes, matching +the existing prompt-oracle schema field. The scored-assertion approval projection is exactly: + +```json +{ + "domain": "AcidSlide scored assertion inventory review v1", + "inventory": "" +} +``` + +`inventory_sha256` is `sha256:` of those JCS bytes. At freeze, each document +requires at least two approval objects with distinct `reviewer_id` values, and every approval must +carry the recomputed projection hash. Counting objects, `uniqueItems`, or accepting arbitrary +well-formed hashes is insufficient. A change to any projected field invalidates every prior approval; +approval metadata itself is outside the projection to avoid a self-hash cycle. ### 13.2 Gold deck design principles @@ -755,13 +1306,20 @@ Each slide should combine several failure modes at once rather than isolating on - include multilingual content - include rotated text boxes, but not true vertical East Asian layout -### 13.4 Baseline calibration +### 13.4 Baseline measurement Before public release, generate baseline scores from: - **Human expert**: a skilled PowerPoint author recreating the deck from the **exact official inputs** (deck-level prompt, per-slide prompts, reference images, asset manifest). This measures the ceiling for prompt interpretation by a human. -- **Programmatic copy**: a script using `python-pptx` that reads the gold deck's OOXML and reconstructs it programmatically (no direct file copy). This measures the ceiling for structural fidelity achievable via the python-pptx API. -- **Naive LLM**: current frontier model with no benchmark-specific tuning, using the exact official inputs. +- **Programmatic copy**: a published, content-addressed script using a pinned `python-pptx` version that reads the gold deck's OOXML and reconstructs it programmatically (no direct file copy). This is a descriptive API ceiling, not independent oracle evidence. +- **Naive LLM**: a named model, immutable provider model/version identifier, dated API configuration, exact prompt bundle, seed/temperature where supported, and published generation transcript hashes, with no benchmark-specific tuning. + +Baselines run as explicit `run_kind: baseline_control` through the complete conformance harness. They +are permanently `eligible: false`, cannot reserve campaign slots or appear in leaderboard/model +profiles, and publish their descriptive provenance. Gold duplicate detection still runs and is +reported; for this control kind only, a duplicate result does not suppress downstream diagnostic +scoring. They carry the fixed label `grading-verified baseline control; not a leaderboard result`. +Hosted baseline controls require a maintainer signature. Public submission behavior is unchanged. These baselines establish the score distribution and verify that the benchmark discriminates meaningfully. Expected ranges: @@ -769,7 +1327,7 @@ These baselines establish the score distribution and verify that the benchmark d - Programmatic copy: 0.90–1.0 (near-perfect structure, possible visual differences from python-pptx rendering quirks) - Naive LLM: 0.20–0.60 (significant structural and visual gaps) -If baselines fall outside these ranges, the checklist or threshold needs revision before release. +If baselines fall outside these ranges, publish and investigate the result. Do not revise the checklist, threshold, or gold merely to fit the anticipated bands. A diagnosed contract defect requires restarting the affected prompt/oracle freeze and all dependent calibration. ## 14. Proposed Slide Matrix (Non-Normative) @@ -865,39 +1423,158 @@ Includes: chart, table, allowed image, multilingual text, rotated text, overlap, The grader uses a three-layer inspection model: -- **ECMA-376 schema validation**: validates the `.pptx` against the official RELAX NG / XSD schemas from the ECMA-376 5th Edition standard +- **ECMA-376 schema validation**: validates the `.pptx` against the bundled ECMA-376 5th Edition Part 1 Transitional XSD schema set - **OOXML structural inspection**: direct XML inspection for semantic verification of object types, relationships, and properties - **Reference renderer export**: LibreOffice Impress headless for visual export and comparison - **Deterministic checklist execution engine** -**Canonical source of truth**: OOXML package inspection is authoritative for structural properties. Reference renderer (LibreOffice) export is authoritative for visual appearance. Schema validation runs first and reports a `schema_valid` boolean, but schema-invalid files are NOT automatically rejected (see Stage 0.5). +**Canonical source of truth**: scored assertions declare whether OOXML inspection, reference rendering, +or both are authoritative. The same content-addressed MCE-resolved package is consumed by XSD +validation, semantic inspection, and rendering. A schema-invalid, unresolved, or incompletely mapped +package may receive diagnostics but is never verified, eligible, passed, or ranked. ### 15.1 Major grader stages #### Stage 0. Ingestion and quarantine -- validate file extension is `.pptx` +- the long-lived API performs only streaming byte-count, upload timeout, magic-byte, and opaque + object-storage checks; it does not open ZIP or XML content +- a fresh disposable quarantine sandbox validates file extension and package content - validate file size is within limits (max 100 MB) - validate ZIP structure (reject ZIP bombs: max decompression ratio 20:1, max decompressed size 500 MB) - scan for and reject: VBA macros, ActiveX controls, OLE embedded objects, external links, password protection - validate slide count matches expected tier count - load manifest and checklist definitions - ensure benchmark package version match - -All quarantine checks run in the same Docker container as the grader. +- compute `submission_sha256` while streaming and store the opaque upload under an immutable + content-addressed object version + +All archive and XML inspection runs in a disposable, resource-limited, no-egress quarantine +sandbox before the grading sandbox is created. Local and hosted modes use the same normative +quarantine library and evasion-fixture corpus. The API/control-plane process never parses an +untrusted ZIP member or XML document. + +Stages 0 and 0.5 execute in the same disposable sandbox. The sandbox emits a signed quarantine verdict +containing the original `submission_sha256`/size/object version, quarantine-profile hash, MCE-profile +hash, schema-bundle/root-map hashes, `canonical_package_hash_profile_sha256`, gold byte/canonical +hashes, `run_kind`, +`control_authorization_sha256` plus immutable authorization object version (both null for submissions), +server-issued `job_id`, conditional submission/campaign/slot binding (non-null only for submissions), +single-use `verdict_id`, issued/expiry timestamps, and verdict. It signs RFC 8785 canonical JSON with +an Ed25519 key whose +`key_id` and public key are in the active service configuration; rotation uses an audited overlap +window. Queue messages contain only that envelope and immutable identifiers. Before any package parse, +the grading worker verifies signature, key status, expiry, single-use verdict ID, and campaign binding, +then reads the immutable resolved- +package object and recomputes digest and size; any mismatch is a terminal +`quarantine_handoff_mismatch`. The worker never opens the original upload. Thus all first-pass parsing +of attacker-controlled ZIP/XML occurs only inside the disposable quarantine sandbox, and every later +stage consumes the exact schema-valid resolved package that sandbox produced. + +An `accept` verdict additionally requires non-null sanitized +`mce_resolved_package_sha256`/size/object version, computed candidate +`canonical_package_hash_v1`, and a duplicate outcome permitted by its run-kind authorization: +`submission` requires `clear`; `reference_control` requires the authorized exact gold duplicate; +`baseline_control` records either outcome and follows its authorization. A `reject` verdict sets resolved and +candidate fields to null unless safe processing completed far enough to compute them, and carries a +stable diagnostic code; it is never dispatched to a worker. Schema-invalid and gold-duplicate reject +verdicts are committed directly as the completed-ineligible diagnostic outcomes in §11.1.1, while a +security rejection has no report. These conditional forms are schema-enforced. + +The worker also recomputes the candidate canonical package hash using the verdict-bound profile and +requires exact equality with the bound value and duplicate outcome before Stage 1. For controls it +verifies the separate purpose-scoped authorization in §18.4.1. Any missing profile, computed hash, +comparison result, run-kind authorization, or cross-binding fails closed before parsing. + +##### Signed-verdict replay state machine + +The durable verdict store is authoritative and transitions atomically: + +`issued -> leased(generation, worker_id, lease_deadline) -> consumed`. + +- issuance inserts a unique `verdict_id` in `issued`, generation 0, with the signed expiry; +- dispatch compare-and-swaps `issued` to `leased`, increments generation, records one worker and a + lease deadline no later than verdict expiry, and emits a dispatcher-signed lease token binding all + four values; +- the worker verifies both envelope and lease token, rehashes the resolved object, then atomically + changes its exact lease generation to `consumed` immediately before the first package parse; +- `consumed`, `expired`, and `revoked` are terminal. No delivery, worker, retry, or operator action may + parse using that verdict ID again; +- an expired lease may return to `issued` only when durable state proves `parse_started_at` and report + are both absent and the signed verdict itself has not expired. The next claim increments generation; + a delayed worker holding an older generation is rejected; +- a failure after consumption requires a complete fresh quarantine execution and a new verdict ID. + The old verdict is linked as superseded but never reset. Verdict expiry before consumption releases + a campaign reservation only under the pre-report rules in §11.1.1. + +State transition, lease acquisition, parse-start, and report/slot commit use serializable transactions +or equivalent compare-and-swap constraints. The conformance corpus includes concurrent delivery, +lease timeout/redelivery, delayed stale worker, two-worker claim, crash immediately before and after +consumption, expired signature, revoked key, and fresh-verdict retry fixtures; at most one worker may +reach package parsing for one verdict. #### Stage 0.5. ECMA-376 schema validation -- validate the `.pptx` PresentationML content against ECMA-376 Part 1 **Transitional** schemas (RELAX NG from `schemas/ecma-376/relaxng-transitional/`). Transitional is used because virtually all real-world .pptx files target transitional conformance, not strict. -- log all schema violations -- a file that fails schema validation is **not automatically rejected** (many real-world .pptx files have minor schema violations) but schema violations are reported and a `schema_valid` boolean is included in the report +Stage 0.5 is the sanitizing second half of the disposable quarantine job, not a parser inside the API +or long-lived grading worker. + +- preprocess Markup Compatibility and Extensibility using the normative, content-addressed + `schemas/mce-profile-v1.json` before validation. That profile enumerates the exact namespace URIs + understood for `Requires` evaluation; extension namespaces are unsupported unless explicitly listed +- fail on undeclared prefixes, malformed QName lists, an unsupported `mc:MustUnderstand` namespace, + or `mc:AlternateContent` with neither a supported `mc:Choice` nor an `mc:Fallback` +- for `mc:AlternateContent`, select the first `mc:Choice` whose complete `Requires` set is understood, + otherwise select `mc:Fallback`, then recursively process only the selected branch +- for unsupported ignorable elements and attributes, apply `mc:ProcessContent`, + `mc:PreserveElements`, and `mc:PreserveAttributes` exactly as declared by the profile: processed + child content remains in the validation tree, ignored markup is removed from the validation tree, + and preserved unknown markup is recorded byte-for-byte in sidecar evidence but is never interpreted +- apply identical MCE output to XSD validation and semantic inspection; graders MUST NOT validate one + tree and score another +- deterministically serialize every processed XML part back into a schema-valid, content-addressed + `mce_resolved_package`. XSD validation, Stage 1 rendering, and Stage 3 semantic inspection consume + only this package; the original upload is retained solely for provenance and duplicate detection +- validate the resulting `.pptx` PresentationML content against the bundled ECMA-376 Part 1 **Transitional** XSD schema set from `schemas/ecma-376/xsd-transitional/`. Transitional is used because virtually all real-world `.pptx` files target transitional conformance, not strict. +- before XSD success, enforce the complete frozen OPC package profile: + - `[Content_Types].xml` has exactly one `Default` per lowercase extension and at most one `Override` + per normalized part name; each existing part has exactly one unambiguous effective content type, + every override names an existing part, and declared content type/root pairs match the root map + - part names and relationship targets satisfy the OPC URI grammar and RFC 3986 resolution used by + ECMA-376: absolute ZIP names, backslashes, query/fragment, empty/`.`/`..` segments, invalid or + non-canonical percent escapes, encoded separators, control/NUL bytes, non-NFC names, and trailing + slash parts are rejected. Normalized-name and Unicode case-fold collisions are rejected + - `/_rels/.rels` exists with exactly one internal Transitional `officeDocument` relationship to + `/ppt/presentation.xml`; relationship IDs are unique per source and every `.rels` part is located + only at its OPC-defined relationship-part name + - every internal relationship target is resolved against its source part, normalizes to an existing + package part, and has the expected content type; dangling targets and illegal URI forms fail. + External relationships are forbidden by Stage 0 and never dereferenced + - every non-metadata part is reachable from the package root relationship graph; orphan parts, + duplicate ZIP member names, and parts omitted from `[Content_Types].xml` fail closed + - `/ppt/presentation.xml` contains exactly one `p:sldSz` with + `cx=12192000`, `cy=6858000` EMU and a slide-ID list exactly matching the campaign's 5/12/20 + resolved slide relationships +- reject every relevant XML part whose content type/root-element pair is absent from the frozen + schema mapping. Unknown, ambiguous, or multiply mapped roots fail closed; they are not skipped +- publish the MCE profile hash, XSD bundle hash, and content-type/root-element-to-XSD mapping in + the scoring manifest and every report; log all preprocessing and schema violations +- a file that fails schema validation receives only the fail-closed diagnostic form described in + §11.1.1: `verification_complete`, `eligible`, and `deck_passed` are false, its occupied campaign + contribution is `0.0`, and its sanitized run row is public but never ranked as eligible #### Stage 1. Reference renderer export -- open submitted `.pptx` in LibreOffice Impress headless within the canonical Docker environment -- export all slides to PNG at 1920 × 1080 -- enforce per-submission timeout (max 120 seconds for open + export) -- if LibreOffice fails to open the file, the submission is marked as `failed` with a retryable error +- open the content-addressed `mce_resolved_package` in LibreOffice Impress headless within the + canonical Docker environment +- export exactly one PDF, then rasterize every page with the pinned Poppler `pdftoppm` and normalize + with the pinned Pillow encoder to RGB PNG at exactly 1920 × 1080, as specified in §9.5 +- enforce a 120-second component timeout for LibreOffice open/PDF export inside the separate + 10-minute hosted-job timeout; Poppler and normalization have their own manifest-pinned limits +- distinguish infrastructure failure from an artifact-deterministic open/export failure exactly as + §11.1.1 specifies; only the former is `failed`/retryable, while a reproduced artifact failure + commits a completed-ineligible diagnostic result and occupies its slot at `0.0` +- direct PNG export, an alternate rasterizer, resizing, or rendering the unresolved upload is a + grading error and makes verification incomplete #### Stage 2. Visual comparison @@ -905,16 +1582,17 @@ All quarantine checks run in the same Docker container as the grader. - compute perceptual similarity score (SSIM) per slide - also compute exact pixel match (reported as a stretch metric) - emit diff visualization for debugging -- pass/fail threshold: SSIM ≥ 0.9999 (strict perceptual match; calibration per §22 may only tighten) +- pass/fail threshold: SSIM ≥ 0.9999 using the frozen §22.1 profile; validation checks but never + changes this v1 value #### Stage 3. OOXML structure extraction -- inspect the uploaded `.pptx` ZIP contents directly for structural analysis +- inspect only the content-addressed `mce_resolved_package` for structural analysis - inspect slide XML (PresentationML) - inspect slide layout and master relationships - inspect media parts and relationships - inspect charts, tables, placeholders, and theme references -- validate all embedded media hashes against asset manifest (using two-tier hash model per §8.3) +- validate all embedded media hashes against the primary asset hashes in §8.3 #### Stage 4. Scene graph normalization @@ -926,6 +1604,8 @@ All quarantine checks run in the same Docker container as the grader. #### Stage 5. Checklist evaluation +- materialize the targeted tier item set with the exact §6.2 algorithm and verify its scoring-manifest + hash before evaluating any item - run slide-level items with severity scoring - run deck-level items with severity scoring - run automatic-fail anti-cheat rules @@ -935,6 +1615,8 @@ All quarantine checks run in the same Docker container as the grader. #### Stage 6. Reporting - generate machine-readable JSON report +- validate the terminal-state conditionals and compute both the full report hash and the +content-addressed score-semantic projection defined in §26.1.1 - generate optional HTML report - include slide-by-slide pass/fail, severity, and diff artifacts - include efficiency metrics @@ -981,15 +1663,19 @@ This representation is extracted from: - **OOXML package inspection** (primary source for all structural properties: object types, hierarchy, text content, geometry, relationships) - **Reference renderer export** (supplementary source for render-derived geometry verification: bounding box positions as rendered at 1920×1080) -The gold scene graph is committed to the benchmark package for transparency and regression testing. +The gold scene graph is committed for transparency, regression testing, and visual-diff alignment. +It is not an independent oracle and cannot create or waive a scored requirement. Scored structural +expectations come from the frozen prompt requirements inventory and independently reviewed +checklist (§13.1). ## 17. Structural Comparison Rules ### 17.1 Required comparison behavior -The structural comparator requires: +The structural comparator evaluates only properties named by each frozen scored assertion. Depending +on the item-specific matching/equivalence policy it may require: -- exact object count per slide for required objects +- exact object count for objects constrained by that assertion - correct object type correspondence (semantic, not literal) - correct group nesting correspondence (semantic equivalence per §5.2) - correct ordering correspondence where user-visible @@ -1039,31 +1725,102 @@ Flag as automatic failures when: ### 18.2 Allowed image rules -Only images whose embedded content hash matches the asset manifest's two-tier hash model (§8.3) may appear — either the primary hash or an accepted recompression hash. No other re-encoded variants are accepted. PowerPoint's internal thumbnail and preview artifacts are excluded from this check. +Only images whose embedded content hash matches the asset manifest's primary SHA-256 (§8.3) may appear. Re-encoded variants are not accepted in v1. PowerPoint's internal thumbnail and preview artifacts are excluded from this check. Verification methods: -- hash all embedded media parts against the manifest's primary and recompression hash sets +- hash all embedded media parts against the manifest's primary hashes - compare dimensions against manifest-defined expected dimensions per asset -- compare crop values against the gold deck's crop for the specific slide position where the asset appears (within ±2px tolerance measured in export-resolution pixels at 1920×1080) — the same asset may legitimately appear with different crops on different slides +- compare crop values only when a prompt- or reference-image-sourced assertion specifies the crop for + that slide position (within its frozen tolerance); the same asset may legitimately appear with + different crops on different slides - detect any non-manifest raster objects and measure their area -- compare against gold asset inventory +- compare required/allowed usage against asset-manifest-sourced assertions, never an extracted gold + asset inventory ### 18.3 Hidden object hacks Flag as failures when: -- incorrect objects are placed fully off-canvas with no corresponding gold off-canvas object -- incorrect content is hidden under opaque objects (z-order analysis reveals covered non-gold objects) -- extra objects beyond gold object count are hidden off-canvas or under opaque layers +- objects violate a frozen prompt/reference-image assertion for visible on-canvas placement or a + prompt-sourced assertion for intentional off-canvas placement +- incorrect content is hidden under opaque objects in violation of a frozen assertion +- objects outside the bounded optional counts declared by assertions are hidden off-canvas or under + opaque layers ### 18.4 Higher-level gaming prevention -The following are tracked and flagged (not automatic failures in v1, but reported): +The following receive `disposition: warning` and are reported without changing the score: - submissions that appear to be hard-coded deck synthesis (e.g., near-perfect structural match with zero visual customization from prompt) - submissions with metadata indicating non-model generation tools -- multiple submissions that are byte-identical or differ only in metadata +- multiple non-gold submissions that are byte-identical or differ only in metadata + +An artifact matching either published gold duplicate hash (§1.1) receives `disposition: reject`, +ineligibility code `gold_artifact_copy`, and is never leaderboard-eligible. Near-match and hard-coded synthesis +heuristics remain warnings because v1 cannot reliably distinguish benchmark-specific generation +from copying after a semantically inert modification. + +This rejection applies whenever `run_kind: submission`, in hosted or local mode. The conformance +harness has a separate explicit `run_kind: reference_control` used only by release tests and the drift +canary. It accepts only the gold hashes embedded in the active scoring manifest, sets +`eligible: false`, bypasses campaign/leaderboard publication, and cannot carry submitter/model +attribution. Hosted reference controls additionally require a maintainer signature; a public API key +cannot request or emulate them. Reference-control reports are published as operational evidence, +never as leaderboard runs, with the distinct fixed label +`grading-verified reference control; no generation attribution`. + +The separately defined `baseline_control` path in §13.4 also remains permanently ineligible and +outside campaigns. It may continue diagnostic scoring after recording `gold_artifact_copy`; this +exception is not exposed by `POST /submissions` and cannot produce a public submission result. + +#### 18.4.1 Signed control authorization envelopes + +`submission`, `reference_control`, and `baseline_control` are separate signed handoff contracts, not +a client-selectable string. Every quarantine verdict binds `run_kind`. A submission verdict requires +`control_authorization_sha256: null`, a real campaign/slot binding, and the ordinary duplicate policy +`reject_and_complete_ineligible`. Any control field on a public submission is a handoff mismatch. + +A reference or baseline control requires a separate RFC 8785 canonical control-authorization +envelope validated by `schemas/control-handoff.schema.json` and signed by a currently authorized, +purpose-scoped maintainer key distinct from API keys and quarantine-verdict keys. The authorization +binds `authorization_id`, `run_kind`, exact purpose (`release_reference`, `drift_canary`, or +`descriptive_baseline`), original/resolved/canonical artifact identities, scoring manifest/cohort, +all profile hashes, requested tier, no-campaign/no-slot policy, duplicate disposition, issuer key ID, +issued/expiry timestamps, and a single-use nonce. The quarantine verdict includes the authorization +envelope hash and signature result; the worker independently verifies both signatures, key purposes, +expiry, nonce state, and all cross-envelope bindings before parsing. + +For `reference_control`, artifact identities must equal the exact gold identities in §13.1.1, +duplicate disposition is `allow_reference_only`, and downstream scoring must be perfect while +remaining unpublished from leaderboard/model paths. For `baseline_control`, the authorized baseline +evidence ID and artifact hashes must match its published evidence, duplicate disposition is +`record_then_continue_diagnostic`, and output remains descriptive/ineligible. Neither control may +name a campaign, slot, submitter, model, or model revision. A missing, wrong-purpose, expired, +replayed, cross-bound, or API-key-signed authorization fails before worker parsing. Control results +use their distinct verification labels and can never be converted into submission rows. + +#### 18.4.2 Canonical gold-duplicate profile + +The release publishes `schemas/canonical-package-hash-v1.json` as a content-addressed normative +profile. It defines the exact included OPC parts, accepted content types, normalized part-name +ordering, XML Canonicalization method, relationship normalization, binary-part treatment, and the +only ignored volatile core-property nodes/attributes. ZIP timestamps, compression, member ordering, +and other container metadata never affect the result. Duplicate normalized part names, orphan parts, +unknown content types, unmapped XML roots, or non-profile extensions are rejected rather than omitted +from the hash. No implementation may add an ignore rule locally. + +The canonical hash input is the Stage 0.5 `mce_resolved_package`, not the unresolved ZIP. The gold +canonical hash is computed through the identical MCE/root-map/profile pipeline. The original-upload +byte hash remains a separate exact-copy guard. A profile/version/hash mismatch makes duplicate +screening incomplete and the run ineligible; it never falls back to byte-hash-only screening. + +The §13.1.1 gold evidence publishes the original-byte SHA-256, resolved-package SHA-256, +`canonical_package_hash_profile_sha256`, and `canonical_package_hash_v1`. The +conformance corpus contains the exact gold, a ZIP-repacked copy, copies with every individually +ignored volatile field changed, and close non-gold controls. Every gold-derived case must reject and +every declared non-gold control must remain distinguishable. Passing this guard is duplicate +screening only; it does not verify generation provenance. For hosted mode, model attestation (§25.7) provides additional gaming prevention. @@ -1075,12 +1832,13 @@ V1 includes: - Arabic (RTL) - Japanese (CJK) -The grader verifies: +For each applicable prompt-sourced assertion, the grader verifies: - exact Unicode text content - editability as real text (not rasterized, not outlined) - correct RTL text direction where required -- correct line breaking and layout behavior as represented in the gold deck +- correct line breaking and layout behavior where constrained by a prompt- or + reference-image-sourced assertion - no transliteration - no outlining - no rasterization @@ -1090,9 +1848,9 @@ The grader verifies: Some slides are intentionally impossible to pass structurally unless the submission uses masters/layouts correctly. -The grader verifies: +For each applicable prompt-sourced assertion, the grader verifies: -- the expected slide layout is referenced in OOXML +- the assertion-required slide layout is referenced in OOXML - repeated elements come from master/layout where required by the prompt - required content is placed in the correct placeholder types - visually correct manual copies do not count as passing when the prompt specifies master/layout usage @@ -1101,15 +1859,16 @@ Checks: - compare layout references in OOXML - inspect placeholder metadata -- compare expected inherited objects versus slide-local objects +- compare assertion-required inherited objects versus slide-local objects ## 21. Native Tables, Charts, and Fields ### 21.1 Tables -If the prompt explicitly calls for a table, the grader requires: +If the prompt explicitly calls for a table, the grader requires a native OOXML table. The remaining +properties below are required only when named by a frozen prompt- or reference-image-sourced +assertion: -- native OOXML table object (not grouped shapes) - correct row/column count - correct placement within geometry tolerance - correct visible styling and content @@ -1117,9 +1876,10 @@ If the prompt explicitly calls for a table, the grader requires: ### 21.2 Charts -If the prompt explicitly calls for a chart, the grader requires: +If the prompt explicitly calls for a chart, the grader requires a native OOXML chart. The remaining +properties below are required only when named by a frozen prompt- or reference-image-sourced +assertion: -- native OOXML chart object - correct chart type - correct visible series/labels/legend behavior - correct axis formatting where specified @@ -1133,7 +1893,11 @@ Where specified, the grader requires native slide-number, date, or footer fields ### 22.1 Official rule - exported submitted slide PNG is compared to exported gold slide PNG using SSIM (Structural Similarity Index) -- pass threshold: SSIM ≥ 0.9999 (this is the v1 default; calibration per §22.3 may only **tighten** this threshold, never loosen it) +- pass threshold: SSIM ≥ **0.9999**; this value is frozen for v1 and validation does not tune it +- inputs are two same-shaped `uint8` RGB arrays at 1920 × 1080; a missing or differently sized image fails rather than being resized +- the normative call is scikit-image `structural_similarity` with `channel_axis=2`, + `data_range=255`, `win_size=7`, `gaussian_weights=false`, `use_sample_covariance=true`, + `K1=0.01`, and `K2=0.03`; the exact scikit-image and NumPy versions are pinned in the scoring manifest - exact pixel match is also computed and reported as a stretch metric but is not the pass/fail criterion ### 22.2 Rationale for perceptual threshold @@ -1147,25 +1911,26 @@ Exact pixel matching is desirable but may be infeasible due to: SSIM ≥ 0.9999 is extremely strict while tolerating renderer-level noise that does not reflect generation quality. The exact detection power (e.g., whether a single misplaced character triggers failure) depends on the character's size and position; the threshold is validated empirically during calibration. -### 22.3 Threshold calibration +### 22.3 Fixed-threshold validation -Before release, the threshold is calibrated using both positive and negative fixtures: +Before release, the already frozen threshold is validated using both positive and negative fixtures: -**Positive calibration (self-export stability):** +**Positive validation (self-export stability):** - exporting the gold deck 100 times in the pinned environment -- computing SSIM between all export pairs -- verifying self-comparison SSIM is consistently ≥ 0.99999 +- computing SSIM for all 4,950 unordered run pairs and all 99,000 corresponding page pairs +- verifying every per-page minimum and the global minimum SSIM are ≥ 0.99999 - if not, investigating and resolving instability before releasing -**Negative calibration (rejection power):** +**Negative validation (rejection power):** - creating controlled negative fixtures with known single-element mutations (moved text box, changed font size, wrong color, missing object) - computing SSIM for each negative fixture against the gold export - verifying that all negative fixtures score below the pass threshold -- if any negative fixture passes, tightening the SSIM threshold (the v1 visual rule is SSIM-only; if SSIM alone cannot discriminate, the export environment must be tightened, not the scoring rule) - -The final threshold is set to maximize the gap between the worst self-export pair and the best negative fixture. +- verifying every required negative fixture scores below the frozen `0.9999` threshold +- if any negative fixture passes, the benchmark is not releaseable; the environment, prompts, gold, +or mutation design must be corrected and the complete validation rerun. The threshold is not tuned + to fit desired baseline outcomes -**v1 visual rule freeze**: the official v1 visual pass/fail rule is SSIM-only (no region-aware supplementary checks). If calibration reveals that SSIM alone cannot discriminate between self-exports and negative fixtures, the benchmark must tighten the export environment (not add undocumented supplementary rules). Region-aware checks may be added in a future MAJOR version with a new calibration cycle. +**v1 visual rule freeze**: the official v1 visual pass/fail rule is SSIM-only (no region-aware supplementary checks). If validation reveals that SSIM alone cannot discriminate between self-exports and negative fixtures, the benchmark must tighten the export environment without changing the scoring rule, then restart the complete environment/oracle freeze and validation. If the fixed rule still cannot discriminate, v1 is not releasable. Region-aware checks require a future MAJOR version with a new freeze and validation cycle. ### 22.4 Practical safeguard @@ -1173,20 +1938,26 @@ If LibreOffice export is not stable enough even in a pinned Docker environment, ## 23. Reference Implementation Stack -**Implementation authority**: where this spec defines the contract (what is checked, pass/fail criteria, scoring rules), the reference implementation in `grader/` is authoritative for algorithmic details (exact SSIM parameters, anti-cheat geometry computation methods, opacity thresholds, etc.). The reference implementation's behavior IS the spec for any detail not explicitly defined in this document. Third-party implementations must match the reference implementation's output on the published test fixtures. +**Implementation authority**: the frozen OpenSpec, scoring manifest, schemas, and published fixture +expectations define the contract. A mutable checkout is not normative. Algorithmic details that can +affect a score—including SSIM parameters, geometry matching, opacity thresholds, tie-break rules, +and PNG normalization—MUST be explicit in the scoring manifest or a content-addressed normative +file it references. Third-party implementations must produce byte-identical §26.1.1 score-semantic +report projections on the published conformance corpus. The recommended reference grader stack is: - Python `3.12+` -- `lxml` for OOXML XML inspection and ECMA-376 RELAX NG schema validation +- `lxml` for OOXML XML inspection and ECMA-376 XSD schema validation - `zipfile` for `.pptx` package extraction - `Pillow`, `numpy`, and `scikit-image` for visual comparison (SSIM) - `pydantic` for normalized scene graph models and API schemas - `pytest` for regression tests -- LibreOffice Impress headless (pinned version) for slide export to PNG +- LibreOffice Impress headless (pinned version) for PDF export and pinned Poppler `pdftoppm` for PNG + rasterization - Docker for reproducible environment packaging -ECMA-376 schema files (RELAX NG from `schemas/ecma-376/relaxng-transitional/`) are bundled in the grader package for schema validation. +ECMA-376 XSD schema files from `schemas/ecma-376/xsd-transitional/` are bundled in the grader package for schema validation. **XML hardening**: all `lxml` usage for untrusted submissions must use a hardened parser: ```python @@ -1206,10 +1977,12 @@ No Windows, COM automation, or Microsoft Office dependency exists in the referen ### 24.1 Positive control tests -- gold deck scores perfect across all tiers +- three maintainer-signed `reference_control` jobs (one per tier) score perfect without entering a + campaign or leaderboard - exported gold images match stored references (SSIM = 1.0) - normalized gold scene graph is stable across repeated extractions -- baseline scores (§13.4) are within expected ranges +- baseline scores (§13.4) exist with complete provenance; deviations from descriptive bands are + published and investigated but do not fail this control ### 24.2 Negative control tests @@ -1233,10 +2006,14 @@ Create intentionally broken fixtures that each fail a narrow set of checks: - missing bullet/paragraph semantics - incorrect line spacing - wrong gradient fill +- every individual OPC fault in §15.1: duplicate/ambiguous content type, invalid/colliding part name, + missing or duplicate root officeDocument relationship, illegal/dangling relationship target, + orphan part, incorrect `p:sldSz`, slide-ID/count mismatch, and wrong PDF page count/box/rotation ### 24.3 Mutation tests -Automated mutators that alter gold deck structure and verify expected checklist failures: +Automated mutators alter independently validated positive fixtures—including the gold control where +appropriate—and verify the assertion inventory's predeclared checklist failures: - delete object - duplicate object @@ -1262,6 +2039,13 @@ Automated mutators that alter gold deck structure and verify expected checklist - verify machine-readable report schema against normative JSON Schema - verify HTML report rendering - verify efficiency metrics capture +- start from an opaque hostile-capable upload and prove disposable quarantine emits a signature-valid + verdict plus immutable resolved object; prove the worker atomically consumes the verdict, never + receives/parses the original, runs Stages 1–6, commits a schema-valid report and slot atomically, + and publishes a byte/hash-matching immutable public row +- run the same path for eligible, schema-invalid zero-slot, gold-duplicate zero-slot, artifact-render + zero-slot, handoff mismatch, service failure/release, reference-control, and baseline-control cases +- verify every full report round-trips through the §26.1.1 semantic projection schema/JCS/hash process ### 24.6 Hosted service tests @@ -1271,35 +2055,272 @@ Automated mutators that alter gold deck structure and verify expected checklist - webhook delivery tests: verify callback on completion with correct HMAC signature - leaderboard consistency tests: verify that leaderboard entries match stored run records - concurrent submission tests: verify fairness under load - -### 24.7 Baseline acceptance bands - -- Human expert: fidelity_score in [0.85, 0.98] — if outside, review checklist item difficulty -- Programmatic copy: fidelity_score in [0.90, 1.0] — if below 0.90, review structural comparison rules -- Naive LLM: fidelity_score in [0.20, 0.60] — if above 0.60, the benchmark may be too easy; if below 0.20, prompts may be underspecified +- control-plane isolation tests: instrument the API process and prove it never opens an untrusted ZIP + member or parses untrusted XML +- quarantine handoff integrity tests: mutate object bytes/version/digest between quarantine and worker + dispatch and require `quarantine_handoff_mismatch` before parsing +- verdict replay tests: concurrent two-worker claim, stale lease generation, lease expiry before parse, + crash before/after consume, signature/key expiry, and fresh-verdict retry prove at most one parse per + verdict ID +- control-authorization tests: submissions cannot request control kinds; wrong-purpose/API/quarantine + keys, campaign-bound controls, mismatched gold/baseline identities, and replayed authorizations fail + before parsing +- campaign contract tests: prove immutable single-tier/single-variant binding, first-three slot + occupation including zeroed graded-ineligible runs, atomic three-campaign robustness groups, and no + alias/quota reset +- scoring-cohort tests: prove mismatched manifest, grader-tree, or environment hashes never aggregate +- verification-label schema tests: prove every public/API result includes the exact v1 constant +- tier-selection tests: prove the exact §6.2 item sets/hashes for tiers 1/2/3, including deck items, + affected-slide intersection, and rejection of tier/slide inconsistency +- release-chain tests: reject rollback, fork, gap, same-sequence alternate hash, invalid state, + premature effective time, revoked signature, and cache-clearing rollback attempts + +### 24.7 Descriptive baseline bands + +- Human expert: anticipated fidelity_score in [0.85, 0.98] +- Programmatic copy: anticipated fidelity_score in [0.90, 1.0] +- Naive LLM: anticipated fidelity_score in [0.20, 0.60] + +These ranges are hypotheses, not release acceptance targets. Results outside them are published and +investigated; they do not authorize tuning the checklist, threshold, or gold to obtain a preferred +ranking. A diagnosed contract defect requires restarting the affected prompt/oracle freeze. ## 25. Hosted Service Architecture ### 25.1 Service overview -The AcidSlide hosted service accepts `.pptx` submissions via API, grades them in a controlled environment, and publishes verified scores to a public leaderboard. Only hosted-mode scores appear on the official leaderboard. +The AcidSlide hosted service accepts `.pptx` submissions via API, grades them in a controlled +environment, and publishes grading-verified artifact scores to a public leaderboard. Only hosted-mode +artifact scores appear on the official leaderboard with the label required by §1.1. Generation provenance remains attested in v1, as +defined in §1.1. ### 25.2 Submission API **Base URL**: `https://api.acidslide.dev/v1` -#### POST /submissions +All response objects that contain or summarize a score include these immutable constants: -Create a new submission. +```json +{ + "verification_scope": "artifact_conformance", + "verification_label": "grading-verified artifact score; generation-attested" +} +``` + +#### POST /models + +Register display metadata and issue an immutable model identity for the authenticated submitter. + +Request metadata part: + +```json +{ + "display_name": "string (required)", + "claimed_owner_name": "string (optional, attested)" +} +``` + +Response (`201 Created`): ```json +{ + "submitter_id": "uuid (derived from API key)", + "model_key": "uuid (server-issued)", + "display_name": "string", + "owner_attribution": "submitter-attested", + "created_at": "ISO 8601" +} +``` + +Display names are mutable presentation metadata; `submitter_id` and `model_key` never change and are +the only identity fields used for authorization, quotas, grouping, and comparison. New identities +default to `submitter-attested`; only a separate maintainer verification workflow may set +`owner-verified`, with an immutable audit record. Clients cannot self-assert the verified state. + +#### POST /models/{model_key}/revisions + +Issue an immutable revision before its first campaign. + +Request: + +```json +{ + "display_version": "string (required)", + "revision_note": "string (required)", + "provider_revision": "string (optional, attested immutable provider identifier)" +} +``` + +Response (`201 Created`): + +```json +{ + "model_key": "uuid", + "model_revision_key": "uuid (server-issued)", + "display_version": "string", + "revision_note": "string", + "created_at": "ISO 8601" +} +``` + +The revision payload is immutable after creation. Only display-label corrections may be stored as +separate audited aliases; they never change the original record or historical rows. + +#### POST /generation-profiles + +Register the exact self-hash-free generation configuration before campaign creation. + Request: + +```json { - "model_id": "string (required) — unique model identifier", - "model_version": "string (required) — model version string", + "model_revision_key": "uuid (required)", + "profile": { + "schema_version": "1.0", + "profile_id": "acidslide-generation-profile-v1", + "canonicalization": "RFC8785-JCS", + "generator": { + "provider": "provider name", + "model_identifier": "provider model ID", + "immutable_revision": "provider immutable revision", + "api_surface": "API/product surface" + }, + "generation_strategy": "direct | code | hybrid | template-edit", + "toolchain": [], + "sampling": { + "temperature": null, + "top_p": null, + "top_k": null, + "max_output_tokens": null, + "other_parameters": [] + }, + "permissions": { + "human_intervention_permitted": false, + "post_processing_permitted": false + } + } +} +``` + +The server validates `profile` against `schemas/generation-profile.schema.json`, RFC 8785 +canonicalizes it, computes `generation_profile_sha256`, and returns that digest plus the immutable +stored profile (`201`, or the original response for an idempotent replay). The client cannot supply +the digest. The profile is scoped to the authenticated submitter and named immutable model revision; +it cannot be changed or deleted after any campaign references it. Campaign creation rejects an +unknown, cross-tenant, wrong-revision, schema-invalid, or digest-mismatched profile. + +#### POST /campaigns + +Precommit one reliability campaign before any artifact is uploaded. + +Request: + +```json +{ + "model_revision_key": "uuid (required)", + "scoring_cohort_id": "sha256:... (required, currently active cohort)", "tier": "integer (required) — 1, 2, or 3", - "benchmark_version": "string (required) — e.g. acidslide-v1.0.0", - "prompt_variant": "string (optional) — canonical (default), paraphrase-a, paraphrase-b", + "prompt_variant": "canonical | paraphrase-a | paraphrase-b (required)", + "assistance_class": "unassisted | human-assisted (required)", + "generation_profile_sha256": "sha256:... (required; registered immutable profile)" +} +``` + +Response (`201 Created`): + +```json +{ + "campaign_id": "uuid (server-issued)", + "submitter_id": "uuid (derived)", + "model_key": "uuid (derived)", + "model_revision_key": "uuid", + "benchmark_version": "acidslide-v1.0.0 (derived from cohort)", + "scoring_cohort_id": "sha256:...", + "tier": 3, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": "sha256:...", + "window_id": "server-issued seven-day window identifier", + "opens_at": "ISO 8601", + "closes_at": "ISO 8601", + "accepts_until": "ISO 8601 (derived; initially closes_at)", + "cutoff_release_index_sha256": null, + "slot_count": 3, + "occupied_slots": 0, + "status": "open" +} +``` + +The service derives submitter/model/version/benchmark/window from authenticated immutable records and +the active cohort. The tuple in §11.1 is unique. Client-supplied free text cannot alter binding or +create another campaign in the same window. + +#### GET /campaigns/{campaign_id} + +Returns the immutable binding plus ordered slot state. Before completion, `official_score` is `null` +and `status` is `open | provisional | closed-incomplete`; after three report-producing slots it is +`completed` and returns their arithmetic mean, best, worst, standard deviation, and public run IDs. +Those statistics use `campaign_contribution`, not nullable diagnostic fidelity. +Every completed score object includes the exact `verification_scope` and `verification_label` +constants and all four cohort fields from §9.4. Only the owner can read private reservation/job state; +the public response contains completed run IDs only. + +#### POST /robustness-groups + +Atomically precommit the three standard variants for one tier. + +Request: + +```json +{ + "model_revision_key": "uuid (required)", + "scoring_cohort_id": "sha256:... (required)", + "tier": "integer (required) — 1, 2, or 3", + "assistance_class": "unassisted | human-assisted (required)", + "generation_profile_sha256": "sha256:... (required)" +} +``` + +Response (`201 Created`): + +```json +{ + "robustness_group_id": "uuid", + "tier": 3, + "scoring_cohort_id": "sha256:...", + "assistance_class": "unassisted", + "generation_profile_sha256": "sha256:...", + "window_id": "string", + "campaigns": { + "canonical": "uuid", + "paraphrase-a": "uuid", + "paraphrase-b": "uuid" + }, + "status": "open" +} +``` + +Creation is all-or-nothing. The three child campaigns share submitter/model/revision, tier, cohort, +assistance class, generation-profile hash, and window; each retains its own first-three slots. A child campaign cannot be linked to two groups or +replaced after creation. The robustness score is the minimum of the three completed campaign means. + +#### GET /robustness-groups/{robustness_group_id} + +Returns the immutable group binding, three enum-keyed child campaign IDs/statuses, and +`robustness_score: null` until every child is complete. A completed response includes the minimum +child mean, cross-variant mean and standard deviation as descriptive fields, the exact verification +constants, and all cohort fields. No partial group is ranked. + +#### POST /submissions + +Create a new submission. + +Request metadata part: + +```json +{ + "campaign_id": "uuid (required) — precommitted reliability campaign", + "generation_seed": "string | null (required; exact provider-facing seed or null)", "efficiency_metrics": { "generation_strategy": "string (required) — direct | code | hybrid | template-edit", "generation_wall_clock_seconds": "number (optional, attested)", @@ -1315,14 +2336,29 @@ Request: "post_processing": "boolean (required)", "external_resources_used": "boolean (required)", "external_resources_description": "string (required if external_resources_used is true, else omit)" - } + }, + "webhook_url": "https://example.com/callback (optional)", + "webhook_secret": "string (required only with webhook_url; write-only)" } +``` File: multipart upload of .pptx (max 100 MB) -Response (202 Accepted): +The service derives `submitter_id`, `model_key`, `model_revision_key`, `benchmark_version`, +`scoring_cohort_id`, `tier`, `prompt_variant`, and window from `campaign_id`; the request cannot +override them. The submission's attestation and registered generation profile must match the +campaign's assistance class and generation-profile hash. An accepted upload reserves the next +ordinal, but the slot becomes occupied only when +a grading report exists. A report with `eligible == false` occupies that ordinal with campaign score +`0.0`; a service failure before report creation releases the reservation for retry. + +Response (`202 Accepted`): + +```json { "submission_id": "uuid", + "campaign_id": "uuid", + "campaign_slot": "integer (1, 2, or 3)", "status": "queued", "estimated_wait_seconds": "integer", "status_url": "/submissions/{submission_id}" @@ -1333,37 +2369,90 @@ Response (202 Accepted): Poll submission status. -```json Response: + +```json { "submission_id": "uuid", + "campaign_id": "uuid", + "campaign_slot": 1, "status": "queued | grading | completed | failed | rejected", "result": { + "grading_mode": "hosted", + "verification_scope": "artifact_conformance", + "verification_label": "grading-verified artifact score; generation-attested", + "scoring_cohort_id": "sha256:...", + "scoring_manifest_sha256": "sha256:...", + "grader_source_tree_sha256": "sha256:...", + "environment_attestation_sha256": "sha256:...", + "canonical_package_hash_profile_sha256": "sha256:...", + "canonical_package_hash_v1": "sha256:...", + "gold_duplicate_check": "clear", + "targeted_tier": 3, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": "sha256:...", + "generation_seed": null, + "schema_validation_performed": true, + "schema_valid": true, + "visual_verification_performed": true, + "verification_complete": true, + "scoring_completed": true, + "disqualification_state": "none", + "ineligibility_reasons": [], "fidelity_score": 0.847, + "campaign_contribution": 0.847, "passed_items": 287, "total_items": 312, "deck_passed": false, "eligible": true, "anti_cheat_flags": [], "repair_triggered": false, - "tier_scores": { "level_1": 0.95, "level_2": 0.88, "level_3": 0.847 }, + "tier_scores": { + "level_1": null, + "level_2": null, + "level_3": { "fidelity_score": 0.847, "passed": 287, "total": 312 } + }, "report_url": "/submissions/{submission_id}/report" }, - "error": { - "code": "string (e.g., quarantine_rejected, grading_timeout, office_crash, invalid_tier)", - "message": "string", - "retryable": "boolean" - } + "error": null } ``` -**Error codes:** +`result` is `null` until completion. `error` is `null` unless status is `failed` or `rejected`; when +present it uses the common error schema below. `result` and `error` are never both non-null. + +The response validates against `schemas/submission-status.schema.json`. Hosted API results require +`grading_mode: hosted`; its conditionals require: + +- `queued | grading`: both `result` and `error` are null; +- `failed | rejected`: `result` is null and `error` is non-null; +- `completed`: `result` is non-null and `error` is null; the result always includes schema/visual/ + verification-performed state, `scoring_completed`, `disqualification_state`, sorted unique `ineligibility_reasons`, and + canonical-hash profile/digest/comparison fields; and +- `eligible: true` iff `verification_complete`, schema performed/valid, visual performed, no repair, + duplicate check clear, and `disqualification_state == none`. Otherwise eligibility/deck pass are + false. A completed-ineligible result has campaign contribution `0.0` even if a diagnostic + `fidelity_score` is present; if complete scoring was never performed its fidelity and tier scores + are null as specified in §11.1.1. + +**Stable error and ineligibility codes:** `failed`/`rejected` terminal responses place their code in +the common `error` envelope. `completed` diagnostic responses place the applicable code in sorted +`result.ineligibility_reasons` and keep top-level `error: null`. - `quarantine_rejected`: file failed security scan (not retryable) - `grading_timeout`: grading exceeded 10-minute limit (retryable) - `renderer_crash`: LibreOffice crashed or hung during grading (retryable) -- `invalid_tier`: slide count doesn't match requested tier (not retryable) -- `invalid_benchmark_version`: requested version not found or frozen (not retryable) +- `artifact_renderer_failure`: the same resolved artifact deterministically failed open/export in + two fresh workers (completed-ineligible; not retryable) +- `resource_not_found`: campaign does not exist or is not owned by the API-key submitter (not retryable) +- `campaign_closed`: campaign window has closed (not retryable) +- `campaign_full`: three report-producing slots are already occupied (not retryable) +- `campaign_binding_mismatch`: artifact slide count or server state conflicts with campaign binding (not retryable) +- `invalid_scoring_cohort`: requested cohort is unknown, inactive, or component hashes do not match (not retryable) - `rate_limited`: submission limit exceeded (retryable after wait) +- `gold_artifact_copy`: upload matches the published gold byte hash or + `canonical_package_hash_v1` (not retryable) +- `quarantine_handoff_mismatch`: worker bytes do not match the signed quarantine verdict (not retryable) **Webhook support (optional):** @@ -1387,54 +2476,149 @@ Webhook delivery: Download full JSON or HTML report. -#### GET /leaderboard?view={summary|detail} +#### GET /leaderboard -Query parameters: -- `view`: `summary` (default) groups by `model_id`, showing best version per model. `detail` lists every `(model_id, model_version)` entry. +Returns completed campaign results grouped only within an exact scoring cohort. Display labels are +never used as grouping keys. -```json Response (summary view): + +```json { "benchmark_version": "acidslide-v1.0.0", + "grader_version": "1.0.0", + "verification_scope": "artifact_conformance", + "verification_label": "grading-verified artifact score; generation-attested", + "scoring_cohort_id": "sha256:...", + "scoring_manifest_sha256": "sha256:...", + "grader_source_tree_sha256": "sha256:...", + "environment_attestation_sha256": "sha256:...", + "grader_package_sha256": "sha256:...", + "oci_image_digest": "sha256:...", + "prompt_bundle_sha256": "sha256:...", + "scored_assertion_inventory_sha256": "sha256:...", + "checklist_bundle_sha256": "sha256:...", + "schema_bundle_sha256": "sha256:...", + "schema_root_map_sha256": "sha256:...", + "mce_profile_sha256": "sha256:...", + "canonical_package_hash_profile_sha256": "sha256:...", + "asset_manifest_sha256": "sha256:...", + "font_manifest_sha256": "sha256:...", "updated_at": "ISO 8601", "entries": [ { - "model_id": "string", - "model_version": "string", - "tier_scores": { - "level_1": { - "best_score": 0.95, - "mean_score": 0.93, - "worst_score": 0.90, - "submission_count": 3, - "robustness_score": 0.91 - }, - "level_2": { "...same structure..." }, - "level_3": { "...same structure..." } - }, - "aggregate_score": 0.82, - "efficiency": { "...best submission's efficiency metrics..." }, - "submitted_at": "ISO 8601", - "environment_hash": "string" + "submitter_id": "uuid", + "model_key": "uuid", + "model_revision_key": "uuid", + "campaign_id": "uuid", + "model_display_name": "string (attested display metadata)", + "model_revision_display": "string (attested display metadata)", + "owner_attribution": "owner-verified | submitter-attested", + "tier": 3, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": "sha256:...", + "official_score": 0.93, + "record_score": 0.95, + "worst_score": 0.90, + "standard_deviation": 0.0216, + "submission_count": 3, + "campaign_status": "completed", + "robustness_group_id": "uuid | null", + "robustness_score": 0.88, + "completed_at": "ISO 8601", + "scoring_cohort_id": "sha256:..." } ] } ``` -**Leaderboard publication rule**: all submissions with `eligible == true` are published. There is no qualification gate — every eligible submission appears on the leaderboard. +**Leaderboard publication rule**: every campaign with at least one public completed run appears, +including provisional and stale campaigns with those labels. Each row represents exactly one tier and +one prompt variant, assistance class, and generation profile. Rankings include only completed +three-run campaigns in the current scoring cohort and are partitioned by the complete §11.5 selection +key. +Robustness is a separate parent-group value and appears only when all three child campaigns are +complete. No "best version" roll-up is presented as an official model result. + +#### GET /leaderboard/runs -**Summary view version selection**: the summary view selects the `model_version` with the highest Level 3 `best_score` (or highest available tier if Level 3 was never submitted). If a model has no Level 3 submissions, it uses Level 2, then Level 1. +Returns every append-only public summary for a completed grading run without aggregation loss. +Security-rejected uploads and jobs that failed before grading expose no attacker-controlled metadata. +Raw submissions, full reports, and diff artifacts remain private under §25.7.1. + +Every row includes `verification_scope`, `verification_label`, campaign/slot/variant/tier bindings, +assistance class, generation-profile hash, nullable generation seed, all scoring-cohort fields from +§9.4, `canonical_package_hash_profile_sha256`, artifact byte/canonical hashes, the recomputed +candidate digest and gold duplicate-check outcome, score/eligibility/disqualification state, every +anti-cheat disposition and affected-slide list, attestation, and timestamps. #### GET /leaderboard/history Historical leaderboard snapshots for tracking progress over time. +#### Resource and state invariants + +The normative OpenAPI and database migration encode these minimum resources and constraints: + +- `model_identity(model_key PK, submitter_id, display_name, owner_attribution, created_at)`; immutable + identity fields, audited display-label aliases only +- `model_revision(model_revision_key PK, model_key FK, immutable_payload_json, + immutable_payload_sha256, created_at)`; no update/delete after creation +- `generation_profile(generation_profile_sha256 PK, submitter_id FK, model_revision_key FK, + canonical_profile_json, created_at)`; hash is recomputed from RFC 8785 bytes, profile is immutable, + and authorization is tenant/revision scoped +- `scoring_cohort(scoring_cohort_id PK, scoring_manifest_sha256, + grader_source_tree_sha256, environment_attestation_sha256, benchmark_version, state)`; a database + constraint or trigger verifies the §9.4 derivation +- `campaign(campaign_id PK, submitter/model/revision/cohort FKs, tier, prompt_variant, + assistance_class, generation_profile_sha256, window_id, opens_at, closes_at, status)` with a + uniqueness constraint over the complete §11.1 key +- `robustness_group(robustness_group_id PK, + identity/cohort/tier/assistance_class/generation_profile_sha256/window binding)` and exactly three + child links unique by `(robustness_group_id, prompt_variant)` and by child `campaign_id` +- `submission_reservation(submission_id PK, campaign_id FK, slot_ordinal, state, created_at)` with + unique `(campaign_id, slot_ordinal)` and ordinal constrained to 1..3 +- `grading_run(run_id PK, submission_id UNIQUE FK, immutable_public_json, + immutable_public_sha256, created_at)`; append-only and never updated or deleted + +Slot reservation is serialized transactionally per campaign. `reserved -> occupied` occurs exactly +once when any grading/diagnostic report is committed; ineligible reports persist score `0.0` for +campaign aggregation. `reserved -> released` is allowed only for a service failure proven to occur +before any report was committed. Campaign completion, robustness completion, and leaderboard +aggregates are derived from immutable occupied runs, never mutable cached scores. Database migrations +must enforce these invariants under concurrent submissions, not only application code. + +Every mutating endpoint requires an `Idempotency-Key`. Keys are scoped to authenticated submitter and +route for 24 hours: replaying the same canonical request returns the original status/body, while reuse +with a different payload returns `409 idempotency_conflict`. Errors use one schema: + +```json +{ + "error": { + "code": "stable_machine_code", + "message": "non-sensitive human description", + "retryable": false, + "request_id": "uuid" + } +} +``` + +Authentication failure is `401`; authorization failures and non-owned opaque resource IDs both return +`404 resource_not_found` to prevent cross-tenant enumeration; invalid state transitions return `409`; +schema errors return `422`; rate limits return `429` with `Retry-After`. The OpenAPI enumerates the +endpoint-specific stable codes, including `identity_not_found`, `revision_immutable`, +`campaign_conflict`, `robustness_group_conflict`, and the submission codes below. + ### 25.3 Authentication and rate limiting - API key authentication (issued per organization) - Rate limits: - 10 submissions per hour per API key - - 3 submissions per `(model_id, model_version, benchmark_version, prompt_variant)` tuple per 7-day window + - one three-run campaign per `(submitter_id, model_key, model_revision_key, scoring_cohort_id, tier, prompt_variant)` per server-issued 7-day window + - organization-level monthly quota applies across every model/revision key and cannot be reset by registering aliases + - every transport-accepted upload counts against hourly/monthly quotas even if quarantine rejects it + or its campaign reservation is later released - 100 MB max file size per submission - 5 concurrent grading jobs per API key - Quota: @@ -1448,13 +2632,26 @@ Historical leaderboard snapshots for tracking progress over time. [Upload] → [Quarantine] → [Queue] → [Worker Dispatch] → [Grade] → [Store] → [Publish] ``` -1. **Upload**: receive .pptx, validate size/extension, assign submission_id -2. **Quarantine**: static OOXML scan (same as Stage 0, §15.1), reject malicious files +1. **Upload**: stream opaque bytes while enforcing transport limits, compute `submission_sha256`, + write an immutable object version, and assign submission/campaign reservation IDs; do not open ZIP + or XML in the API process +2. **Quarantine**: dispatch a fresh hardened sandbox running normative Stages 0 and 0.5; produce the + schema-valid MCE-resolved package for accepted artifacts, emit the conditionally complete signed + verdict binding both original and resolved digest/size/object versions plus every profile/hash + outcome, and convert security, schema/OPC, and duplicate failures to their exact §11.1.1 terminal + forms without ZIP/XML parsing in the API process 3. **Queue**: priority queue with per-tenant fairness, estimated wait time -4. **Worker dispatch**: assign to an isolated Docker container -5. **Grade**: execute grader stages 0-6 with per-job timeout (max 10 minutes) +4. **Worker dispatch**: assign the immutable resolved-package object version plus signed verdict to an + isolated Docker container; rehash before any package parse and fail on mismatch; never dispatch the + original upload to the grader +5. **Grade**: verify and atomically consume the signed handoff/lease, then execute grader Stages 1–6 + against only the resolved package with per-job timeout (max 10 minutes). Stages 0/0.5 are never + rerun in or linked into the long-lived worker process 6. **Store**: write immutable run record with full provenance -7. **Publish**: update leaderboard for all submissions with `eligible == true` +7. **Publish**: append a public leaderboard run row for every completed `submission` report, + including ineligible zero-score campaign slots; publish reference/baseline controls only in their + separately labeled operational/descriptive evidence collections; update campaign/robustness + aggregates only within the exact cohort ### 25.5 Worker isolation model @@ -1463,28 +2660,48 @@ Each grading job runs in a fresh, ephemeral Docker container: - container is created from the canonical grading Docker image (§9.7) - no network egress from the container during grading - no persistent state between jobs (container is destroyed after grading completes) -- LibreOffice crash recovery: if LibreOffice hangs or crashes, the container is killed after timeout and the job is marked as `failed` with a retryable error +- LibreOffice crash recovery follows §11.1.1: the container is killed after timeout, but only an infrastructure-attributed crash/timeout is + `failed`/retryable; a failure reproduced from the same resolved artifact in a fresh worker is a + completed-ineligible artifact outcome - worker pool auto-scales based on queue depth using standard container orchestration (Kubernetes, ECS, etc.) - containers are Linux-based — no Windows or Office licensing required at any scale - security hardening: rootless containers, read-only rootfs, dropped capabilities (`--cap-drop=ALL`), `--security-opt=no-new-privileges`, seccomp profile, CPU/memory/PID limits, no host mounts beyond controlled scratch space ### 25.6 Results storage and provenance -Each grading run produces an immutable record containing: - -- submission_id -- benchmark_version (e.g., `acidslide-v1.0.0`) -- grader_version (git hash) +Each grading job produces an immutable kind-conditional record containing: + +- grading_mode (`local | hosted`); service records and every public row require `hosted` +- verification_scope and the exact verification_label from §1.1 +- run_kind (`submission`; `reference_control`/`baseline_control` use separate signed, non-leaderboard + conditionals in the report schema) +- submission_id, campaign slot ordinal, prompt variant, and robustness-group ID if any +- submitter_id, model_key, model_revision_key, campaign_id, targeted tier, assistance class, + generation-profile SHA-256, and nullable generation seed +- original submission SHA-256, MCE-resolved-package SHA-256, and `canonical_package_hash_v1` +- `canonical_package_hash_profile_sha256`, gold byte hash, gold + `canonical_package_hash_v1`, recomputed candidate canonical digest, and duplicate-check result +- benchmark_version, scoring_cohort_id, scoring_manifest_sha256, + grader_source_tree_sha256, and environment_attestation_sha256 +- prompt, checklist, schema/XSD, MCE-profile, asset, and font bundle hashes +- grader package hash - libreoffice_version (exact build string) -- docker_image_hash (canonical Docker image hash) -- font_bundle_hash -- asset_manifest_hash +- Poppler, Python, Pillow, NumPy, scikit-image, and lxml versions +- OCI image digest and platform - grading_started_at / grading_completed_at (UTC) -- environment_attestation (combined hash of all environment parameters) +- environment attestation payload whose canonical SHA-256 matches + `environment_attestation_sha256` +- targeted score, every flag with disposition, and submitter attestation +- full report SHA-256 and §26.1.1 `score_semantic_report_sha256` - full JSON report - per-slide diff artifacts (stored in object storage, retained for 90 days) -Scores from different environment attestation hashes are comparable only within the same benchmark version. +For `grading_mode: hosted, run_kind: submission`, the public leaderboard run row exposes every applicable field above except raw +artifacts, private report details, and diff files. Control records require null +submission/campaign/model fields and are exposed only in the separate evidence collections from +§18.4.1. Scores are comparable or aggregatable only when `scoring_cohort_id` and all three component +hashes in §9.4 match exactly. The service recomputes the cohort ID before publication. Benchmark- +version equality alone is insufficient. ### 25.7 Model attestation @@ -1498,12 +2715,14 @@ Leaderboard entries require attestation: Submissions with `human_intervention: true` are displayed in a separate leaderboard section ("Human-Assisted"). -Attestation is on the honor system in v1. Automated verification (e.g., requiring the model to generate via an API endpoint the service calls directly) is planned for v2 ("Execution Mode"). +Attestation is on the honor system in v1. It is displayed as **generation-attested**, never as +generation-verified. Automated generation verification (e.g., requiring the model to generate via +an API endpoint the service calls directly) is planned for v2 ("Execution Mode"). ### 25.7.1 Report and artifact access control - **Full JSON reports** are visible only to the submitter (authenticated via API key) -- **Leaderboard summary data** (scores, model info, efficiency metrics) is public +- **Leaderboard campaign summaries and append-only run rows** described in §§25.2 and 25.6 are public - **Per-slide diff artifacts** are visible only to the submitter for 90 days - **Gold deck exports** and checklist definitions are always public - Submitters may opt to make their full report public (one-way toggle, not reversible) @@ -1518,11 +2737,19 @@ For hosted-mode leaderboard submissions in v1, the generation process is: **v1 limitation**: the service cannot enforce generation-time network restrictions because it only grades uploaded artifacts. The attestation model (§25.7) requires disclosure of external resource use. This is an honor-system disclosure, not a technical enforcement. -In v2 ("Execution Mode"), the service will provide a sandboxed generation environment where the model API is called directly and the output is captured without intermediate human, network, or tool access. Only Execution Mode submissions will be marked as "verified" on the leaderboard. +In v2 ("Execution Mode"), the service will provide a sandboxed generation environment where the +model API is called directly and the output is captured without intermediate human, network, or +tool access. Only Execution Mode submissions may be marked **generation-verified**. This does not +change the v1 guarantee that official hosted scores are grading-verified. -### 25.8.1 Frozen benchmark version submissions +### 25.8.1 Frozen benchmark cohorts -Submissions targeting a frozen benchmark version (§26.4) are rejected with error code `invalid_benchmark_version`. The API returns the list of active benchmark versions in the error response. +Campaign creation against an unknown, frozen, or superseded cohort (§26.4) is rejected with +`invalid_scoring_cohort`; the response lists active cohort IDs and benchmark versions. Existing open +campaigns derive `accepts_until` from the signed freeze/supersede effective time, accept no reservation +at or after it, allow already reserved jobs to finish, then derive `completed` or +`closed-incomplete` under §11.5.1. Their immutable window/closes fields are never rewritten; +completed history remains public. ### 25.9 Abuse prevention @@ -1534,6 +2761,10 @@ Service-level abuse prevention (distinct from benchmark anti-cheat in §18): - **Egress policy**: grading containers have no outbound network access - **Ban/appeal flow**: suspended accounts can appeal via email; response within 5 business days - **Denial-of-service protection**: standard CDN/WAF in front of the API +- **Cross-tenant authorization**: every submission, report, artifact, campaign, and webhook route is covered by IDOR tests using two distinct tenants +- **API-key lifecycle**: keys are stored only as salted hashes and support rotation, overlap windows, immediate revocation, and audit logging +- **Webhook secret handling**: webhook secrets and signed payload keys are never logged or returned after creation +- **SSRF corpus**: tests include DNS rebinding, redirects, IPv4-mapped IPv6, IPv6 zone identifiers, alternate numeric IP forms, and public-to-private resolution changes ### 25.10 Cost model @@ -1549,30 +2780,101 @@ Pricing model: - Organization tier: $1 per submission (covers infra + margin) - Enterprise: custom pricing with SLA +### 25.11 Reliability, observability, and recovery + +V1 launch SLOs and operating signals are explicit: + +- control-plane/API monthly availability target: 99.5%, excluding announced benchmark freezes +- p95 latency below 500 ms for non-upload metadata reads and below 2 seconds from completed upload + body receipt to durable reservation/quarantine dispatch +- 99% of non-abusive grading jobs reach a terminal state within 10 minutes; queue time is measured and + displayed separately from grading time +- backpressure rejects before body upload with `429`/`Retry-After` when durable queue or worker + capacity thresholds are exceeded; it never accepts bytes that cannot be durably tracked + +Structured logs carry `request_id`, immutable tenant/resource IDs, stage, cohort ID, image digest, and +error code. API keys, webhook secrets, raw attestation text, PPTX/XML bytes, and signed URLs are never +logged. Metrics include request/error/latency by route, upload bytes, quarantine disposition, any +handoff mismatch, queue depth/age, worker stage duration/failure, campaign reservations/occupancy, +webhook attempts, public-run publication lag, and drift-canary state. Alerts fire immediately on any +drift block or handoff mismatch, and on sustained API/queue/worker SLO breach. + +The relational database uses automated encrypted backups with point-in-time recovery; immutable +object versions and public-run rows have lifecycle policies that preserve the retention promised by +§25.6/§25.7.1. Before launch, a restore drill must recover campaign/run consistency into an isolated +environment and reproduce public-row hashes. Deployments use health-gated rolling replacement and a +documented rollback; a scorer/environment change cannot roll back across cohort identity boundaries. + ## 26. Versioning and Governance ### 26.1 Version scheme `acidslide-vMAJOR.MINOR.PATCH` -- **MAJOR**: new slide set, new tiers, scoring model changes, breaking changes. Scores across major versions are not comparable. -- **MINOR**: new prompt variants, documentation clarifications, new informational fields in reports. Scores are comparable within a major version. **MINOR versions MUST NOT add, remove, or re-weight checklist items or change pass/fail thresholds** — any such change requires a MAJOR version bump. -- **PATCH**: grader bug fixes that do not change scores, documentation updates. No score impact. If a bug fix would change scores, it requires a MAJOR version bump (since MINOR must preserve score comparability). - -### 26.1.1 Rerun policy - -When a PATCH is released, historical submissions are NOT automatically re-graded (since PATCH changes do not affect scores). When a MAJOR version is released, all historical submissions remain scored against their original version. Submitters must explicitly resubmit against the new version. +- **MAJOR**: new slide set, official prompt variants, tiers, assertion/checklist/scoring changes, or any + breaking change. Scores across major versions are not comparable. +- **MINOR**: documentation clarifications, new informational report fields, or explicitly non-scoring + experimental prompt variants. MINOR versions MUST NOT add, remove, or re-weight scored assertions, + change official variants, or change pass/fail rules. The complete conformance corpus must remain + byte-identical at the score-semantic projection layer below. +- **PATCH**: documentation or implementation changes that also produce byte-identical score-semantic + projections for the complete conformance corpus. A score-affecting change requires a MAJOR version. + +### 26.1.1 Score-semantic report projection + +`schemas/report-semantic-projection.schema.json` defines the only cross-build equality surface. From a +schema-valid full report, implementations construct an object containing exactly: projection schema +version; grading mode; run kind; targeted tier and prompt variant; performed/valid/complete stage booleans; +`scoring_completed`; eligibility, disqualification reasons, repair and duplicate outcomes; targeted/tier score and +weighted counts; ordered slide/deck item IDs with pass state, severity, weight, stable outcome code, +and tier-affected slides; ordered anti-cheat rule IDs/dispositions/affected slides; and ordered stable +schema/verification error codes and package part locators. Arrays use the schema-prescribed UTF-8 +item/rule/code ordering and numeric values use JSON numbers permitted by the schema. + +The projection excludes submission/run/campaign/model/tenant IDs, timestamps, durations, URLs, +display/free-text fields, attestation, seeds, artifact/report/diff hashes, all scoring-cohort and +provenance/profile hashes, environment/version identities, stack traces, diagnostics text, and every +additive informational item/metric. It rejects unknown fields. The canonical bytes are RFC 8785 JSON, +and `score_semantic_report_sha256` is their SHA-256. The full report is independently hashed and may +differ across runs or compatible cohorts; it is never the compatibility gate. Changing projection +membership, any included value, or the projection schema is score-semantic and requires a MAJOR +version unless the complete frozen corpus proves the resulting canonical projection bytes unchanged. + +No semantic version claim permits aggregation across scoring cohorts. Projection-identical MINOR/PATCH +cohorts may be displayed as compatible historical cohorts, but §9.4 exact-hash grouping still applies. + +### 26.1.2 Rerun policy + +Historical submissions are never rewritten. A MINOR or PATCH with any changed cohort component +creates a new scoring cohort even when the complete conformance corpus projection is byte-identical; its runs +remain separate. When a MAJOR version is released, submitters must explicitly resubmit. ### 26.2 Grader versioning -The grader is versioned independently. Grader patches are applied to all active benchmark versions. The grader version is recorded in every run record. +The grader is versioned independently. A replacement grader may serve an active benchmark only +after the complete positive, negative, mutation, security, and determinism corpus produces +byte-identical score-semantic projections. It receives a new grader hash and scoring cohort; it is never +aggregated with earlier runs. If any score-semantic projection differs, the change is score-affecting and +requires a new benchmark MAJOR version. ### 26.3 Environment versioning -The Docker/LibreOffice environment is versioned independently. If the environment must be updated (e.g., LibreOffice security patches, font updates), the drift canary (§9.6) validates that scores remain stable. If scores remain stable, the environment is updated in-place with a PATCH note. If scores change, a new benchmark MAJOR version is released (because score-affecting changes require a MAJOR bump per §26.1). +The Docker/LibreOffice environment is versioned independently. An environment is never updated in +place. A replacement OCI digest may serve an active benchmark only after the complete conformance +corpus produces byte-identical score-semantic projections. It forms a new scoring cohort and remains +separate from earlier environment hashes. Any difference requires a new benchmark MAJOR version. ### 26.4 Leaderboard freezing +Release-index state transitions are forward-only on the signed §9.4.3 chain: + +- `active -> frozen -> superseded` is allowed; reversing a state or publishing a lower-sequence + active index is invalid +- exactly one accepted chain head is active for new campaign creation; an index may be issued before + `effective_at`, but does not change serving state until that instant +- workers finish already consumed verdicts against their bound cohort; new reservations and verdicts + use only the effective active head + When a new major version is released: - the previous version's leaderboard is frozen and archived @@ -1591,23 +2893,71 @@ When a new major version is released: ### 27.1 JSON report +The following is an abridged, parseable hosted-submission illustration, not a conformance fixture. +`schemas/report.schema.json` is normative and requires the complete provenance/attestation and +kind/mode/state conditionals described in §§1.1, 11.1.1, and 25.6. + ```json { "benchmark_version": "acidslide-v1.0.0", - "grader_version": "abc123", - "environment_hash": "def456", - "submission": "submission.pptx", + "grading_mode": "hosted", + "run_kind": "submission", + "grader_version": "1.0.0", + "verification_scope": "artifact_conformance", + "verification_label": "grading-verified artifact score; generation-attested", + "scoring_cohort_id": "sha256:...", + "scoring_manifest_sha256": "sha256:...", + "grader_source_tree_sha256": "sha256:...", + "environment_attestation_sha256": "sha256:...", + "grader_package_sha256": "sha256:...", + "oci_image_digest": "sha256:...", + "prompt_bundle_sha256": "sha256:...", + "scored_assertion_inventory_sha256": "sha256:...", + "checklist_bundle_sha256": "sha256:...", + "schema_bundle_sha256": "sha256:...", + "schema_root_map_sha256": "sha256:...", + "mce_profile_sha256": "sha256:...", + "canonical_package_hash_profile_sha256": "sha256:...", + "asset_manifest_sha256": "sha256:...", + "font_manifest_sha256": "sha256:...", + "submission_id": "uuid", + "campaign_id": "uuid", + "campaign_slot": 1, + "targeted_tier": 3, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": "sha256:...", + "generation_seed": null, + "submission_sha256": "sha256:...", + "mce_resolved_package_sha256": "sha256:...", + "canonical_package_hash_v1": "sha256:...", + "gold_submission_sha256": "sha256:...", + "gold_mce_resolved_package_sha256": "sha256:...", + "gold_canonical_package_hash_v1": "sha256:...", + "gold_duplicate_check": "clear", "schema_valid": true, + "schema_validation_performed": true, + "visual_verification_performed": true, + "verification_complete": true, + "scoring_completed": true, + "disqualification_state": "none", + "ineligibility_reasons": [], "repair_triggered": false, "grading_duration_seconds": 23.4, "fidelity_score": 0.847, + "campaign_contribution": 0.847, "passed_items": 287, "total_items": 312, "deck_passed": false, "eligible": true, + "score_semantic_report_sha256": "sha256:...", + "environment_attestation": { + "schema_version": "1.0", + "payload": "validates against schemas/environment-attestation.schema.json" + }, "tier_scores": { - "level_1": { "fidelity_score": 0.95, "passed": 68, "total": 72 }, - "level_2": { "fidelity_score": 0.88, "passed": 165, "total": 188 }, + "level_1": null, + "level_2": null, "level_3": { "fidelity_score": 0.847, "passed": 287, "total": 312 } }, "verified_metrics": { @@ -1624,14 +2974,20 @@ When a new major version is released: "code_language": "python-pptx", "code_line_count": 347 }, - "prompt_variant": "canonical", "attestation": { "method": "GPT-4o with python-pptx tool use", "human_intervention": false, "post_processing": false, "external_resources_used": false }, - "anti_cheat_flags": [], + "anti_cheat_flags": [ + { + "rule_id": "deck.master-reuse", + "disposition": "zero_affected_slides", + "affected_slides": [6], + "tier_affected_slides": [6] + } + ], "slides": [ { "slide": 1, @@ -1670,6 +3026,13 @@ When a new major version is released: } ``` +The example is a hosted submission. `report.schema.json` conditionally requires the exact hosted +label and non-null hosted bindings for that form. A local submission uses the local label and null +hosted identity/campaign/slot bindings required by §1.1, may still have +`scoring_completed: true`/`deck_passed: true`, but always has `eligible: false`, +`campaign_contribution: 0.0`, `disqualification_state: non_official_local`, and +`ineligibility_reasons: ["local_mode"]`. + ### 27.2 Optional HTML report Useful for developers tuning against the benchmark: @@ -1690,7 +3053,10 @@ Deliverables: benchmark package skeleton, grader package skeleton, service API s ### Phase 1. Prompt design and validation (prompt-first) -Deliverables: deck-level prompt, per-slide prompt/spec files, paraphrased variants. Prompts are designed BEFORE the gold deck per §13.1. Independent author validation confirms prompt convergence (≥80% structural similarity). +Deliverables: deck-level prompt, per-slide prompt/spec files, paraphrased variants, and the frozen +prompt-requirements oracle. Prompts are designed BEFORE the gold deck per §13.1. At least three +blinded implementations must each satisfy every mandatory prompt-sourced requirement; pairwise scene- +graph similarity is diagnostic only and has no percentage release gate. ### Phase 2. Gold deck design matrix @@ -1706,15 +3072,20 @@ Deliverables: OOXML parser, ECMA-376 schema validator, normalized scene graph sc ### Phase 5. Visual comparator and anti-cheat rules -Deliverables: SSIM comparator with threshold calibration, media hash inventory checker, full-slide and tiled-raster cheat detection, off-canvas and hidden-content checks, raster-area calculations +Deliverables: SSIM comparator with fixed-threshold validation against the complete positive/negative +corpus, media hash inventory checker, full-slide and tiled-raster cheat detection, off-canvas and +hidden-content checks, raster-area calculations ### Phase 6. Checklist engine Deliverables: declarative checklist schema with severity tiers, evaluator runtime, slide-level and deck-level item execution, per-tier scoring, aggregate fidelity score computation -### Phase 7. Grader test suite and baseline calibration +### Phase 7. Grader test suite and baseline measurement -Deliverables: positive fixtures, negative fixtures (including new anti-cheat cases), mutation harness, determinism tests (100-run export stability), **baseline calibration** (§13.4) — human expert, programmatic copy, and naive LLM baselines scored using the now-complete grading pipeline, verified against acceptance bands (§24.7) +Deliverables: positive fixtures, single-fault negative fixtures (including anti-cheat, MCE, duplicate, +and quarantine-handoff cases), complete assertion mutation matrix, determinism tests (100-run export +stability), and **descriptive baselines** (§13.4)—human expert, programmatic copy, and naive LLM— +published with provenance. Deviations from §24.7 bands are investigated but are not acceptance failures. ### Phase 8. Hosted service MVP @@ -1728,28 +3099,91 @@ Deliverables: versioned benchmark release, grader CLI, benchmark README, submiss `AcidSlide v1` is complete when all of the following are true: +Schemas, empty directories, candidate metadata, and pending review records are not evidence that a +gate passed. While this document is Draft, the release validator MUST fail if concrete signed +`scoring-manifest.json`/`release-index.json`, gold evidence, scene-graph fixtures, baseline evidence, +or reviewer approvals are absent. Those instances are created only from real frozen artifacts and +observed runs; placeholders or synthetic approvals are forbidden. + - benchmark package is fully public and self-contained +- the canonical document header is exactly `Status: Frozen — acidslide-v1.0.0` and the public README + no longer carries a pre-release warning; release-tag CI fails closed on either mismatch +- OpenSpec, OpenAPI, scoring manifest, prompt-requirements oracle, MCE profile, and all normative JSON Schemas are frozen and content-addressed +- the release index and scoring manifest pass JCS/hash/cohort recomputation and an authorized Ed25519 + release signature verifies against `RELEASE_KEYS.json` +- the complete signed release-index chain verifies from trusted genesis through the persisted highest + head; rollback/fork/gap/state/effective-time fixtures fail closed +- grader-source-tree and environment-attestation payloads validate against their normative schemas, + recompute exactly by §§9.4.1–9.4.2, and match every report/cohort field - all bundled fonts are libre/open-source with clear licensing -- gold deck exists and exports stable reference images in the canonical Docker environment (SSIM ≥ 0.99999 across 100 repeated exports, consistent with §22.3) -- baseline calibration scores exist for human expert, programmatic copy, and naive LLM +- canonical `linux/amd64` OCI digest and every renderer/rasterizer/library input are pinned; no mutable runtime dependency remains +- gold deck exists and exports stable reference images in the canonical Docker environment; the + bound §9.4.4 evidence contains exactly 100 runs, 4,950 run pairs, and 99,000 page comparisons, with + every recomputed per-page and global minimum SSIM ≥ 0.99999 (consistent with §22.3) +- one published gold-evidence record binds the same exact MCE-resolved package to OPC/XSD validation, + export, scene graph, duplicate comparison, mutation parentage, and all signed reference controls +- all blinded independent-author prompt-validation rounds pass the frozen prompt requirements oracle +- descriptive baseline scores exist for human expert, programmatic copy, and naive LLM - difficulty tiers (Level 1/2/3) are defined with distinct slide assignments - grader runs fully automatically in the canonical Docker environment (Linux + LibreOffice) -- gold deck scores perfect across all tiers +- three separate signed gold `reference_control` runs (one per targeted tier) score perfect, publish + operational evidence, and cannot enter any campaign or leaderboard path - representative broken fixtures fail the correct checklist items with correct severity +- every scored rule and anti-cheat rule has an independent positive fixture, single-fault negative fixture, and published mutation expectation; every required mutant is killed +- the complete prompt/reference-image/asset assertion inventory has immutable provenance and every + checklist item traces to exactly one assertion; gold OOXML creates no scored requirement +- every assertion validates against the §4.1 provenance compatibility matrix; incompatible + reference-image/asset claims and native/editability claims without prompt provenance fail release +- the full MCE conformance corpus covers supported and unsupported `AlternateContent`, `Ignorable`, + `MustUnderstand`, `ProcessContent`, `PreserveElements`, `PreserveAttributes`, malformed QName data, + and every unmapped content-type/root pair, with fail-closed expected outcomes +- the OPC corpus covers every §15.1 content-type, part-name/case, root-relationship, URI/target, + dangling/orphan, exact `p:sldSz`, slide-count, and PDF page-count/geometry rule with one positive and + single-fault negative fixture per rule +- the canonical package-hash profile is published and its exact-gold, ZIP-repacked-gold, + volatile-metadata, unknown/orphan-part, and close non-gold fixtures all match expected outcomes +- the complete fixed-SSIM-threshold rejection corpus scores below `0.9999`; any scoring-rule change + restarts the freeze or creates a new MAJOR version - image fakery, tiled composite, text-on-raster, and structural cheat cases are caught - multilingual, master/layout, table, chart, field, grouping, z-order, bullet/paragraph, and spacing checks are implemented - fidelity score output is deterministic +- full reports validate their terminal-state conditionals and the complete conformance corpus produces + byte-identical §26.1.1 score-semantic projections under every claimed compatible implementation - severity-weighted scoring produces expected results - no human review is required anywhere in the grading loop - drift canary is operational - hosted service API accepts submissions and returns graded results -- leaderboard displays verified scores with provenance +- leaderboard labels every result exactly `grading-verified artifact score; generation-attested`, rejects published gold duplicate hashes, and exposes immutable public run rows with complete scoring-cohort provenance - quarantine pipeline rejects malicious .pptx files (verified with evasion test suite) +- untrusted ZIP/XML parsing occurs only in the disposable quarantine sandbox, never the API/control plane +- signed quarantine verdicts bind both original and resolved digest/size/object versions plus all + profile/schema/canonical-package hashes, duplicate result, run kind, control authorization, and + campaign/slot identity; the worker verifies Ed25519 signature, expiry, atomic lease generation, + single-use nonce, and binding, receives only the resolved package, rehashes before parsing, and every + tamper/replay/quarantine-to-worker TOCTOU fixture fails closed +- the end-to-end §24.5 gate proves opaque upload → disposable signed quarantine/resolution → one-time + worker consume → Stages 1–6 → atomic report/slot commit → externally readable immutable public row, + including eligible and every required completed-ineligible/pre-report outcome - worker isolation prevents cross-job contamination - version comparability rules are documented and enforced by the API -- leaderboard correctly handles single-tier submissions, multi-submission windows, and model identity grouping +- leaderboard correctly handles single-tier campaigns, first-three-run mean scoring, stable server-issued identity keys, provisional/stale states, robustness campaigns, and strict scoring-cohort separation +- campaign/window conformance proves immutable assistance class and generation-profile hash, nullable + seed propagation, exact UTC window construction, terminal-state/slot table, and full-key default + selection; robustness children match both assistance/profile fields +- campaign conformance tests cover immutable tier/variant bindings, graded-ineligible zero slots, + service-failure slot release, atomic three-child robustness groups, enum-only variants, quota/alias + resistance, exact cohort grouping, and anti-cheat affected-slide intersection with the targeted tier +- every API score, leaderboard campaign, robustness group, and public run row includes exactly + `grading-verified artifact score; generation-attested` and `verification_scope: artifact_conformance` +- normative local reports use exactly `local artifact score; self-reported`, cannot carry hosted + campaign/model bindings, remain ineligible with zero campaign contribution, and are rejected from + every hosted publication path +- production observability covers every §25.11 signal, alert routing is tested, and an isolated + database/object restore drill reproduces immutable campaign and public-run hashes - dispute resolution process is documented and has a designated maintainer -- normative JSON Schemas are published for checklist items and report format +- normative JSON Schemas are published and exercised for checklist items, scored assertions/inventory, + reports and semantic projections, source-tree/environment attestations, release indexes, control + handoffs, submission terminal states, gold evidence, normalized scene graphs, and baseline evidence ## 30. Risks and Mitigations @@ -1759,15 +3193,17 @@ Mitigation: pin LibreOffice version and Docker image, bundle libre metric-compat ### Risk 2. Structural equivalence is harder than visual equivalence -Mitigation: define semantic equivalence classes early (§5.2), build comparison rules from gold deck outward, start with a pilot subset of slides, accept that structural comparison is about semantic correctness not implementation isomorphism +Mitigation: define item-scoped semantic equivalence classes early (§5.2), derive comparison rules from +the frozen scored-assertion inventory, use gold only as a control fixture, and validate alternative +valid implementations plus single-fault mutants before release ### Risk 3. Too many checks become unmaintainable -Mitigation: use declarative checklist format with severity tiers, generate portions of checklist from gold structure, keep item phrasing concise and machine-verifiable +Mitigation: use a declarative checklist with severity tiers, derive scored assertions from the frozen prompt requirements oracle, allow gold extraction only for reviewed diagnostics, and keep item phrasing concise and machine-verifiable ### Risk 4. Gold deck accidentally contains ambiguous implementation choices -Mitigation: use prompt review process (§13.1 step 6), ensure slides that require native constructs explicitly say so in prompts, run baseline calibration to detect unreasonable checklist items +Mitigation: use the prompt-derived requirements-oracle and blinded-author process (§13.1 steps 2–4), ensure slides that require native constructs explicitly say so in prompts, and test multiple valid implementations plus single-fault mutants before the freeze ### Risk 5. Labs overfit the public benchmark @@ -1799,7 +3235,7 @@ Mitigation: attestation model (§25.7) for v1, execution mode (service-controlle The heuristic anti-cheat rules (§18) may flag legitimate submissions. For example, the text-on-raster detection rule may fire on slides with captions positioned near allowed images. -Mitigation: calibrate every anti-cheat heuristic against the full set of passing and failing fixtures before release. Publish the expected false-positive rate per rule. Allow submitters to dispute anti-cheat flags via the governance process (§26.5). Anti-cheat flags do not suppress leaderboard publication — they zero affected slide scores, so the impact is proportional and visible. +Mitigation: validate every anti-cheat heuristic against the full set of passing and failing fixtures before release. Publish the expected false-positive rate per rule. Allow submitters to dispute anti-cheat flags via the governance process (§26.5). Anti-cheat flags do not suppress leaderboard publication — they zero affected slide scores, so the impact is proportional and visible. ### Risk 12. Score churn from environment/grader changes @@ -1813,8 +3249,10 @@ Mitigation: the drift canary (§9.6) detects environment changes. Grader PATCH v 1. Publish normative JSON Schemas for checklist items and report format (encoding the rules in §§10, 12, 27). 2. Publish OpenAPI spec for the hosted-service API (encoding the contracts in §25). -3. Publish the asset manifest schema with recompression hash pre-computation (encoding §8.3). +3. Publish the asset manifest schema with primary byte hashes (encoding §8.3). 4. Validate all schemas against the spec examples to catch inconsistencies before implementation begins. +5. Publish the scoring manifest, prompt-requirements oracle, scored-assertion inventory, MCE profile, + schema/root mapping, canonical-package-hash profile, and complete fixture/mutation index. **Phase B — Benchmark construction:** @@ -1825,14 +3263,16 @@ Mitigation: the drift canary (§9.6) detects environment changes. Grader PATCH v 10. Define the benchmark directory structure and manifest schemas. 11. Author a 5-slide Level 1 pilot deck from validated prompts in LibreOffice Impress. 12. Build the export and scene-graph extraction pipeline against the pilot. -13. Calibrate the SSIM threshold using 100 repeated gold deck exports + negative fixtures. +13. Validate the frozen `0.9999` SSIM threshold using 100 repeated gold exports plus the complete + negative mutation corpus; do not tune it to fit baselines. 14. Validate anti-cheat rules on intentionally broken pilot decks. 15. Expand to Level 2 and Level 3 only after determinism and grading logic are stable. -**Phase C — Calibration and release:** +**Phase C — Baseline measurement and release:** -16. Run baseline calibration and publish baseline scores (requires complete grading pipeline from Phase B). -17. Validate baselines against acceptance bands (§24.7); iterate on checklist or thresholds if needed. +16. Run the three descriptive baselines and publish scores (requires the complete grading pipeline from Phase B). +17. Publish and investigate baseline deviations from the descriptive bands (§24.7). A diagnosed + contract defect restarts the affected freeze; baseline outcomes never authorize tuning. **Phase D — Service deployment:** diff --git a/ACIDSLIDE_REMEDIATION_PLAN.md b/ACIDSLIDE_REMEDIATION_PLAN.md index 5f38397..f2bcf6e 100644 --- a/ACIDSLIDE_REMEDIATION_PLAN.md +++ b/ACIDSLIDE_REMEDIATION_PLAN.md @@ -1,5 +1,9 @@ # AcidSlide v1 — Detailed Remediation Plan +> **Historical and superseded.** This plan describes the retired April draft deck. The draft is +> recoverable from git history at `7f66d66`; it is intentionally absent from the release tree. The +> only current gold is `acidslide-v1/benchmark/deck/gold/acidslide-v1-gold.pptx`. + Goal: take `acidslide-v1/AcidSlide_v1.pptx` (currently auto-failing) and produce a fully conformant AcidSlide v1 gold deck + benchmark package per `ACIDSLIDE_OPENSPEC.md`. > **Key insight**: the spec treats the `.pptx` as only ~5% of the package — most of the work is the *surrounding* artifacts (prompts, checklist YAML, manifests, fixtures, baselines). Fixing the deck without fixing the package still leaves you ungradeable. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..e3d594e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,32 @@ +# Code of Conduct + +## Our commitment + +We are committed to making participation in Gloss respectful and harassment-free for everyone, regardless of background, identity, experience, or point of view. + +## Expected behavior + +- Be specific, curious, and kind when challenging a benchmark claim. +- Critique artifacts, methods, and evidence rather than people. +- Make room for contributors who are new to PowerPoint internals, benchmarking, or open source. +- Disclose conflicts of interest when reviewing results or evidence tied to your own work. +- Accept maintainer decisions about safety, scope, and release integrity. + +## Unacceptable behavior + +- Harassment, threats, discriminatory language, or unwanted sexual attention. +- Publishing another person's private information. +- Deliberately falsifying benchmark evidence or attribution. +- Sustained disruption of issues, reviews, or community spaces. + +## Enforcement + +Report conduct concerns privately through the repository owner's GitHub profile. Maintainers may edit or remove contributions and may temporarily or permanently restrict participation when behavior threatens community safety or project integrity. + +Maintainers will handle reports as privately as practical and will avoid conflicts of interest when assigning reviewers. + +## Scope + +This policy applies in project spaces and when someone is publicly representing Gloss. + +This document is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..14c1821 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,103 @@ +# Contributing to Gloss + +Gloss improves when a benchmark claim becomes easier to inspect, reproduce, or challenge. Small, evidence-backed pull requests are welcome. + +## Good first contributions + +- Add a PowerPoint construct the corpus does not cover. +- Reproduce a grader false positive or false negative. +- Improve a candidate assertion and its mutation fixture. +- Review a prompt requirement, evidence record, or release gate. +- Make the documentation easier to run from a clean checkout. + +Start with an [issue](https://github.com/aronchick/gloss/issues/new/choose). This lets contributors agree on the observable failure before investing in a fixture or implementation. + +## Ground rules + +1. Keep public claims traceable to committed evidence. +2. Do not add invented model results, scores, costs, or generation provenance. +3. Keep the public name **Gloss** and the protocol identifier `acidslide-v1` distinct. +4. Treat the OpenSpec as Draft until the release validator passes and maintainers freeze it. +5. Add or update tests for grader behavior changes. +6. Never commit private slide decks, credentials, customer data, or proprietary fonts. + +## Local setup + +Install [uv](https://docs.astral.sh/uv/), Python 3.12, LibreOffice Impress, and Poppler. Then: + +```bash +git clone https://github.com/aronchick/gloss.git +cd gloss/acidslide-v1/grader +uv sync --extra dev --locked +uv run python ../benchmark/validate_corpus.py +uv run pytest tests/test_mutation_fixtures.py -q +``` + +Run the full grader checks before opening a pull request: + +```bash +uv run ruff check . +uv run ruff format --check . +uv run mypy acidslide tests +uv run pytest --cov=acidslide --cov-fail-under=85 +uv build +uv run pip-audit +``` + +The hosted service has its own locked environment: + +```bash +cd ../service +uv sync --extra dev --locked +uv run ruff check . +uv run ruff format --check . +uv run mypy acidslide_service tests +uv run pytest --cov=acidslide_service --cov-fail-under=85 +uv run pip-audit +``` + +## Adding a benchmark case + +A benchmark change should identify: + +- the natural-language requirement; +- the intended visual and native artifact behavior; +- the affected slides and tier; +- the verification method; +- a positive control; +- a single-fault negative fixture when the check is automatic; +- why the requirement came from the prompt or published assets rather than the gold deck. + +Gold output does not create a requirement. Requirements must remain traceable to the public prompt, references, or allowed assets. + +## Pull requests + +Keep a pull request focused enough to review. In the description, include: + +- the failure or gap; +- the changed contract or behavior; +- exact commands run; +- evidence files added or changed; +- any release claims that remain intentionally blocked. + +CI must pass. Maintainers may ask for a smaller fixture, clearer provenance, or an explicit release-state caveat before merging. + +## Launch surface + +The static site lives in `site/`. Its public counts come from `site/evidence/preview-v1.json`, which is verified against the generated mutation fixture reports by: + +```bash +node launch/verify-launch.mjs +``` + +Rebuild the silent 21-second launch film with: + +```bash +node launch/render-video.mjs +``` + +The renderer requires `rsvg-convert` and `ffmpeg`. Do not hand-edit a published number in the site or video without updating the evidence bundle and its verification source. + +## Conduct and security + +Participation is covered by the [Code of Conduct](CODE_OF_CONDUCT.md). Report vulnerabilities through the process in [SECURITY.md](SECURITY.md), not a public issue. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..07072ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 AcidSlide contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..521b2d3 --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# Gloss + +**Gloss — Generative Layout & OOXML Scoring System** is a public, machine-graded benchmark for PowerPoint artifact conformance against published +prompt, reference-image, and asset requirements. It evaluates native ECMA-376 PresentationML +structure and rendered output in one pinned environment; v1 does not verify which model generated an +artifact. + +**[gloss.tools](https://gloss.tools)** · [Issues](https://github.com/aronchick/gloss/issues) · [Pull requests](https://github.com/aronchick/gloss/pulls) · [Contributing](CONTRIBUTING.md) + +> **A screenshot is not a PowerPoint.** Gloss measures whether generated decks look right and are built right. + +> **Pre-release status:** `ACIDSLIDE_OPENSPEC.md` is still Draft and the release gates are incomplete. +> No deployment should be treated as the official leaderboard until a release announcement names the +> frozen scoring cohort. + +## Technical preview evidence + +The current candidate harness contains 280 schema-valid checks across rendered pixels and native package structure. Its generated operator suite passes 280/280 positive controls and detects 280/280 generated single-fault mutations. This proves configured operator behavior only; it is not independent assertion evidence and it is not a model leaderboard. + +Every launch count is recorded in [`site/evidence/preview-v1.json`](site/evidence/preview-v1.json) and checked against the committed mutation reports by: + +```bash +node launch/verify-launch.mjs +``` + +Release mode intentionally fails until independent prompt convergence, assertion provenance and evidence, reviewer approvals, baselines, environment manifests, and signed release indexes are complete. + +## Score provenance + +- **Local grading** measures a deck on the caller's machine. Local results are self-reported and are not official leaderboard verification. +- **Hosted grading** runs the same grader inside the controlled Gloss environment. Every public + submission score must carry the exact label + `grading-verified artifact score; generation-attested`. +- Generation strategy, token count, cost, retries, and generation time are supplied by submitters. They remain **generation-attested** even when the deck itself was grading-verified. +- A report is not eligible when schema validation did not run or failed, the canonical renderer or + reference exports were unavailable, required slides were not compared, or any required stage was + incomplete. + +## Repository layout + +```text +ACIDSLIDE_OPENSPEC.md Normative v1 contract +acidslide-v1/ + benchmark/ Prompts, assets, candidate checks, gold fixture, and mutation evidence + grader/ Local Python grader and CLI + schemas/ Bundled ECMA-376 Transitional XSD and report schemas + service/ Pre-release hosted API, worker, and leaderboard implementation + Dockerfile Canonical Ubuntu 22.04 grading environment +site/ Static gloss.tools source and launch evidence +launch/ Deterministic film renderer and launch copy +``` + +## Local development + +Requirements: [uv](https://docs.astral.sh/uv/), Python 3.12, LibreOffice Impress, and `pdftoppm` from Poppler. + +```bash +cd acidslide-v1/grader +uv sync --extra dev --locked +uv run acidslide validate ../benchmark/deck/gold/acidslide-v1-gold.pptx +``` + +Full grading is fail-closed until a frozen release supplies signed cohort provenance and the caller +supplies a complete artifact-context handoff. During development, use `validate` for the runnable +quarantine/XSD smoke above. After the v1 release artifacts are published: + +```bash +uv run acidslide grade ../submission.pptx \ + --tier 3 \ + --artifact-context ./artifact-context.json \ + --format json +``` + +Write a standalone report and private visual diffs with: + +```bash +uv run acidslide grade ../submission.pptx \ + --tier 3 \ + --artifact-context ./artifact-context.json \ + --format html \ + --output report.html \ + --artifacts private-diffs/ +``` + +The CLI exits with status `2` when verification could not be completed. A normally graded deck may receive a failing score without making the grading command itself fail. + +## Canonical container + +```bash +docker build -t acidslide-v1 acidslide-v1 +docker run --rm \ + --volume "$PWD:/workspace:ro" \ + acidslide-v1 grade /workspace/submission.pptx --tier 3 \ + --artifact-context /workspace/artifact-context.json --format json +``` + +## Quality gates + +```bash +cd acidslide-v1/grader +uv run ruff check . +uv run ruff format --check . +uv run mypy acidslide tests +uv run pytest --cov=acidslide --cov-fail-under=85 +uv build +uv run pip-audit +``` + +The bundled validator applies deterministic ECMA-376 Markup Compatibility preprocessing before validating against the bundled Part 1 Transitional XSD set. RELAX NG validation is outside the v1 contract. + +## Build it with us + +- [Propose a benchmark case](https://github.com/aronchick/gloss/issues/new?template=benchmark-case.yml) +- [Report a grader gap](https://github.com/aronchick/gloss/issues/new?template=grader-bug.yml) +- [Challenge evidence or a public claim](https://github.com/aronchick/gloss/issues/new?template=evidence-challenge.yml) +- Read [CONTRIBUTING.md](CONTRIBUTING.md) before sending a patch + +## License + +Code and benchmark materials are released under the [Apache License 2.0](LICENSE), except third-party or asset files that carry their own license notices. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..582f196 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,25 @@ +# Security policy + +## Report a vulnerability + +Please do not open a public issue for a security vulnerability. + +Use GitHub's **Report a vulnerability** flow in the repository Security tab. Include: + +- the affected component and commit; +- a minimal reproduction or proof of concept; +- the expected impact; +- whether untrusted `.pptx` input is required; +- any suggested containment or fix. + +If private vulnerability reporting is unavailable, contact the repository owner through the email address on their GitHub profile and ask for a private reporting channel. Do not attach a malicious deck to an unsolicited message. + +## Scope + +The most sensitive surfaces include ZIP/package extraction, XML parsing, LibreOffice rendering, container isolation, upload quarantine, webhook validation, authorization, and result publication. + +The public `gloss.tools` launch page is static. The hosted grading service is pre-release and should not be treated as a production security boundary until a release announcement says otherwise. + +## Response + +Maintainers will acknowledge a complete report as soon as practical, reproduce it privately, and coordinate a fix and disclosure. Timelines depend on severity and maintainer availability. diff --git a/acidslide-v1/.dockerignore b/acidslide-v1/.dockerignore new file mode 100644 index 0000000..1c45944 --- /dev/null +++ b/acidslide-v1/.dockerignore @@ -0,0 +1,24 @@ +.ruff_cache/ +**/.coverage +**/.mypy_cache/ +**/.pytest_cache/ +**/.ruff_cache/ +**/.venv/ +**/__pycache__/ +**/*.py[cod] +grader/build/ +grader/dist/ +service/ + +# Release identities bind the OCI digest and therefore cannot be inputs to the +# environment image whose digest they name. The signed release package is a +# separate read-only runtime mount selected by ACIDSLIDE_BENCHMARK_DIR. +benchmark/environment-attestation.json +benchmark/export-determinism-evidence.json +benchmark/gold-evidence.json +benchmark/runtime-freeze.json +benchmark/scoring-manifest.json +benchmark/release-index.json +benchmark/release-index-chain.json +benchmark/baselines/*.json +benchmark/control-handoffs/*.json diff --git a/acidslide-v1/AcidSlide_v1.pptx b/acidslide-v1/AcidSlide_v1.pptx deleted file mode 100644 index fa6f821..0000000 Binary files a/acidslide-v1/AcidSlide_v1.pptx and /dev/null differ diff --git a/acidslide-v1/Dockerfile b/acidslide-v1/Dockerfile index 84e8133..6e9fc3c 100644 --- a/acidslide-v1/Dockerfile +++ b/acidslide-v1/Dockerfile @@ -1,35 +1,118 @@ -FROM ubuntu:22.04 +ARG SOURCE_DATE_EPOCH=1735689600 + +FROM ghcr.io/astral-sh/uv:0.8.4@sha256:46968e602e1de60a6511cb090ba3945ea8fd9c2e3e321a66111b01baf0cb5ff8 AS uv +FROM ubuntu:22.04@sha256:0d779ea97881505f5ef0039336ee85edba27519bdba968c284c86ee066a973c8 + +ARG SOURCE_DATE_EPOCH + +COPY --from=uv /uv /uvx /bin/ ENV DEBIAN_FRONTEND=noninteractive ENV LANG=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8 ENV TZ=UTC +ENV UV_PYTHON_INSTALL_DIR=/opt/acidslide/python +ENV UV_PROJECT_ENVIRONMENT=/opt/acidslide/venv +ENV PATH=/opt/acidslide/venv/bin:$PATH -RUN apt-get update && apt-get install -y --no-install-recommends \ - libreoffice-impress libreoffice-core \ - fonts-liberation fonts-noto fonts-noto-cjk \ - fonts-crosextra-carlito fonts-crosextra-caladea \ - python3 python3-pip python3-venv \ - locales \ - && locale-gen en_US.UTF-8 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* +# Bootstrap the CA bundle from checksum-pinned snapshot packages, then use one +# immutable Ubuntu snapshot for every APT input. The base image already pins +# libssl3, so only openssl and ca-certificates are needed for HTTPS bootstrap. +ADD --checksum=sha256:8bc80baf8b4a00ed111da33870a958ac9c8a64cb846471381dcc56486747bbec \ + https://snapshot.ubuntu.com/ubuntu/20260401T000000Z/pool/main/o/openssl/openssl_3.0.2-0ubuntu1.21_amd64.deb /tmp/openssl.deb +ADD --checksum=sha256:7b6d6a66bc70a0c0e87893cbe3d0db28e909710ea2f7c6be4d2b74806b1eef75 \ + https://snapshot.ubuntu.com/ubuntu/20260401T000000Z/pool/main/c/ca-certificates/ca-certificates_20240203~22.04.1_all.deb /tmp/ca-certificates.deb -# Font policy: ONLY the packages above are installed. -# Carlito = metric-compatible Calibri; Caladea = metric-compatible Cambria. -# No system default fonts beyond what these packages pull in. +RUN dpkg -i /tmp/openssl.deb /tmp/ca-certificates.deb \ + && rm /tmp/openssl.deb /tmp/ca-certificates.deb \ + && sed -i \ + -e 's|http://archive.ubuntu.com/ubuntu/|https://snapshot.ubuntu.com/ubuntu/20260401T000000Z/|g' \ + -e 's|http://security.ubuntu.com/ubuntu/|https://snapshot.ubuntu.com/ubuntu/20260401T000000Z/|g' \ + /etc/apt/sources.list \ + && apt-get -o Acquire::Check-Valid-Until=false update \ + && apt-get install -y --no-install-recommends \ + libreoffice-impress=1:7.3.7-0ubuntu0.22.04.10 \ + libreoffice-core=1:7.3.7-0ubuntu0.22.04.10 \ + poppler-utils=22.02.0-2ubuntu0.12 \ + locales=2.35-0ubuntu3.13 \ + libfaketime=0.9.8-9 \ + fontconfig=2.13.1-4.2ubuntu5 \ + && test "$(dpkg-query -W -f='${Version}' libreoffice-impress)" = '1:7.3.7-0ubuntu0.22.04.10' \ + && test "$(dpkg-query -W -f='${Version}' libreoffice-core)" = '1:7.3.7-0ubuntu0.22.04.10' \ + && test "$(dpkg-query -W -f='${Version}' poppler-utils)" = '22.02.0-2ubuntu0.12' \ + && test "$(dpkg-query -W -f='${Version}' libfaketime)" = '0.9.8-9' \ + && locale-gen en_US.UTF-8 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* -# Install grader package COPY grader/ /opt/acidslide/grader/ -WORKDIR /opt/acidslide/grader -RUN python3 -m pip install --no-cache-dir -e . - -# Copy benchmark data and schemas COPY benchmark/ /opt/acidslide/benchmark/ COPY schemas/ /opt/acidslide/schemas/ +COPY Dockerfile /opt/acidslide/build/Dockerfile + +# Fontconfig intentionally sees only the 26 content-addressed files in the +# benchmark manifest, even if LibreOffice dependencies ship additional fonts. +RUN install -d /opt/acidslide/fontconfig/cache \ + && printf '%s\n' \ + '' \ + '' \ + '' \ + ' /opt/acidslide/benchmark/fonts/files' \ + ' /opt/acidslide/fontconfig/cache' \ + ' 0' \ + '' \ + > /opt/acidslide/fontconfig/fonts.conf + +ENV FONTCONFIG_FILE=/opt/acidslide/fontconfig/fonts.conf +ENV FONTCONFIG_PATH=/opt/acidslide/fontconfig + +# Freeze wall-clock inputs for LibreOffice and every grader subprocess without +# corrupting timeout/elapsed-time measurements based on monotonic clocks. Apply +# this before building the grader so the installed local project is also +# consistent with the canonical clock under `uv sync --check`. +ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 +ENV FAKETIME="@2025-01-01 00:00:00" +ENV FAKETIME_DONT_FAKE_MONOTONIC=1 +ENV FAKETIME_NO_CACHE=1 +ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} +ENV PYTHONDONTWRITEBYTECODE=1 + +# Install the exact locked Python graph and the grader itself. +RUN uv python install 3.12.11 \ + && uv venv --python 3.12.11 /opt/acidslide/venv \ + && uv sync --frozen --no-dev --no-editable --project /opt/acidslide/grader \ + && fc-cache -f + +RUN /opt/acidslide/venv/bin/python - <<'PY' +import hashlib +import json +import subprocess +from pathlib import Path + +font_root = Path("/opt/acidslide/benchmark/fonts") +manifest = json.loads((font_root / "manifest.json").read_text(encoding="utf-8")) +expected = { + str((font_root / entry["local_path"]).resolve()): entry["sha256"] + for entry in manifest["files"] +} +actual = set( + subprocess.check_output(["fc-list", "-f", "%{file}\\n"], text=True).splitlines() +) +if actual != set(expected): + raise SystemExit( + f"Fontconfig inventory mismatch: missing={sorted(set(expected) - actual)} " + f"extra={sorted(actual - set(expected))}" + ) +for path, expected_sha256 in expected.items(): + actual_sha256 = hashlib.sha256(Path(path).read_bytes()).hexdigest() + if actual_sha256 != expected_sha256: + raise SystemExit(f"Font hash mismatch: {path}") +PY -# Non-root user for security -RUN useradd -m -s /bin/bash grader -USER grader +# Fixed non-root identity for the hosted runner contract. +RUN groupadd --gid 10001 grader \ + && useradd --uid 10001 --gid 10001 --create-home --shell /usr/sbin/nologin grader +USER 10001:10001 WORKDIR /workspace ENTRYPOINT ["acidslide"] diff --git a/acidslide-v1/benchmark/README.md b/acidslide-v1/benchmark/README.md new file mode 100644 index 0000000..294bbe5 --- /dev/null +++ b/acidslide-v1/benchmark/README.md @@ -0,0 +1,51 @@ +# AcidSlide v1 Benchmark Corpus + +This directory contains the public, non-gold benchmark inputs: tier maps, +prompt variants, allowed assets, bundled fonts, and the weighted checklist. +Prompt-derived structural requirements are frozen before gold authoring. +Reference exports later become authoritative only for explicitly provenance- +linked visual assertions; gold OOXML never creates a scored requirement. + +## Integrity validation + +From `acidslide-v1/grader/` using the locked grader environment: + +```bash +uv run python ../benchmark/validate_corpus.py +``` + +This validates prompt-set completeness and hard-constraint parity, checklist +schema/count/ID/severity/source balance, asset dimensions and hashes, and every +bundled font and license record. It does not claim independent-author prompt +convergence. To apply that release gate too: + +```bash +uv run python ../benchmark/validate_corpus.py --release +``` + +Release mode is expected to fail until each file under `prompts/validation/` +records a completed independent-author convergence run. V1 accepts only the +primary asset bytes already pinned in the asset manifest; it does not add +gold-derived recompression hashes. + +## Generated operator mutation fixtures + +From `acidslide-v1/grader/`, rebuild and execute the candidate fixture matrix: + +```bash +uv run python ../benchmark/tools/build_mutation_fixtures.py +uv run python ../benchmark/tools/build_mutation_fixtures.py --check +``` + +The generated index, single-fault expectations, and execution report live in +`fixtures/mutations/`. They prove only that each configured automatic operator +can pass a positive input and detect its generated one-property mutation. They +are not independent prompt/reference/asset evidence, do not complete checklist +evidence or provenance, and do not freeze or approve any candidate assertion. + +## Deterministic rebuild + +`tools/build_corpus.py` regenerates prompt variants, validation records, +manifests, and checklist YAML from the authoritative authoring brief and local +files. It does not create or modify the gold deck, exports, fixtures, baselines, +or hosted-service data. diff --git a/acidslide-v1/benchmark/assets/LICENSE b/acidslide-v1/benchmark/assets/LICENSE new file mode 100644 index 0000000..97a2638 --- /dev/null +++ b/acidslide-v1/benchmark/assets/LICENSE @@ -0,0 +1,21 @@ +AcidSlide v1 Procedural Benchmark Assets + +To the extent possible under law, the AcidSlide benchmark maintainers have +waived all copyright and related or neighboring rights to the three procedural +artworks in this directory. They are made available under CC0 1.0 Universal. + +License text and deed: +https://creativecommons.org/publicdomain/zero/1.0/ + +Covered source files: +- sources/hero-abstract.svg +- sources/cityscape.svg +- sources/texture-pattern.svg + +Covered rendered files: +- mirrored/hero-abstract.png +- mirrored/cityscape.png +- mirrored/texture-pattern.png + +These artworks were authored specifically for AcidSlide v1 and do not include +third-party photographs, logos, trademarks, or generated model output. diff --git a/acidslide-v1/benchmark/assets/manifest.json b/acidslide-v1/benchmark/assets/manifest.json new file mode 100644 index 0000000..35f2d79 --- /dev/null +++ b/acidslide-v1/benchmark/assets/manifest.json @@ -0,0 +1,79 @@ +{ + "schema_version": "1.0", + "policy": "allowlist-only", + "assets": [ + { + "asset_id": "hero-abstract", + "filename": "hero-abstract.png", + "media_type": "image/png", + "dimensions_px": [ + 1920, + 1080 + ], + "source_url": null, + "source_path": "sources/hero-abstract.svg", + "source_sha256": "4323628632d3f7028ac88404e72496b7095d880298ccf243d23d6ff55ce5c4a8", + "local_path": "mirrored/hero-abstract.png", + "sha256": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007", + "accepted_recompression_hashes": [], + "recompression_status": "pending_gold_deck_extraction", + "usage": [ + "slide-01", + "slide-20" + ], + "license": "CC0-1.0", + "license_file": "LICENSE", + "attribution": "AcidSlide benchmark maintainers", + "provenance": "hand-authored procedural SVG rendered locally with librsvg; no third-party or model-generated content" + }, + { + "asset_id": "cityscape", + "filename": "cityscape.png", + "media_type": "image/png", + "dimensions_px": [ + 2400, + 1600 + ], + "source_url": null, + "source_path": "sources/cityscape.svg", + "source_sha256": "4040e29957aeec61c3577261e064e273d7976d972b80fda48c181506a6c28469", + "local_path": "mirrored/cityscape.png", + "sha256": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "accepted_recompression_hashes": [], + "recompression_status": "pending_gold_deck_extraction", + "usage": [ + "slide-07", + "slide-13", + "slide-18" + ], + "license": "CC0-1.0", + "license_file": "LICENSE", + "attribution": "AcidSlide benchmark maintainers", + "provenance": "hand-authored procedural SVG rendered locally with librsvg; no third-party or model-generated content" + }, + { + "asset_id": "texture-pattern", + "filename": "texture-pattern.png", + "media_type": "image/png", + "dimensions_px": [ + 800, + 800 + ], + "source_url": null, + "source_path": "sources/texture-pattern.svg", + "source_sha256": "780e4e63a1a507ee862d9597a13b9d5a81a54a761d4075b028d4313f750305a2", + "local_path": "mirrored/texture-pattern.png", + "sha256": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385", + "accepted_recompression_hashes": [], + "recompression_status": "pending_gold_deck_extraction", + "usage": [ + "slide-07", + "slide-18" + ], + "license": "CC0-1.0", + "license_file": "LICENSE", + "attribution": "AcidSlide benchmark maintainers", + "provenance": "hand-authored procedural SVG rendered locally with librsvg; no third-party or model-generated content" + } + ] +} diff --git a/acidslide-v1/benchmark/assets/mirrored/cityscape.png b/acidslide-v1/benchmark/assets/mirrored/cityscape.png new file mode 100644 index 0000000..535daf6 Binary files /dev/null and b/acidslide-v1/benchmark/assets/mirrored/cityscape.png differ diff --git a/acidslide-v1/benchmark/assets/mirrored/hero-abstract.png b/acidslide-v1/benchmark/assets/mirrored/hero-abstract.png new file mode 100644 index 0000000..43ebda0 Binary files /dev/null and b/acidslide-v1/benchmark/assets/mirrored/hero-abstract.png differ diff --git a/acidslide-v1/benchmark/assets/mirrored/texture-pattern.png b/acidslide-v1/benchmark/assets/mirrored/texture-pattern.png new file mode 100644 index 0000000..498342e Binary files /dev/null and b/acidslide-v1/benchmark/assets/mirrored/texture-pattern.png differ diff --git a/acidslide-v1/benchmark/assets/sources/cityscape.svg b/acidslide-v1/benchmark/assets/sources/cityscape.svg new file mode 100644 index 0000000..63c79b2 --- /dev/null +++ b/acidslide-v1/benchmark/assets/sources/cityscape.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/acidslide-v1/benchmark/assets/sources/hero-abstract.svg b/acidslide-v1/benchmark/assets/sources/hero-abstract.svg new file mode 100644 index 0000000..eed573d --- /dev/null +++ b/acidslide-v1/benchmark/assets/sources/hero-abstract.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/acidslide-v1/benchmark/assets/sources/texture-pattern.svg b/acidslide-v1/benchmark/assets/sources/texture-pattern.svg new file mode 100644 index 0000000..7ad3f27 --- /dev/null +++ b/acidslide-v1/benchmark/assets/sources/texture-pattern.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/acidslide-v1/benchmark/checklist/deck.yaml b/acidslide-v1/benchmark/checklist/deck.yaml index 9f4e71b..9031276 100644 --- a/acidslide-v1/benchmark/checklist/deck.yaml +++ b/acidslide-v1/benchmark/checklist/deck.yaml @@ -1,73 +1,670 @@ -schema_version: "1.0" -id: deck.slide-count -scope: deck -tier: 1 -title: Slide count matches target -description: The submission must contain exactly 20 slides for Level 3 (checked per-tier). -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: slide_count - expectation: - exact_count: 20 ---- -schema_version: "1.0" -id: deck.master-present -scope: deck -tier: 1 -title: At least one slide master defined -description: The deck must define at least one slide master for layout inheritance. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: master_count - expectation: - min_count: 1 ---- -schema_version: "1.0" -id: deck.layouts-defined -scope: deck -tier: 1 -title: Multiple slide layouts defined -description: The deck should define multiple layouts for varied slide types. -kind: master-layout -severity: major -source_of_truth: ooxml -verification: - method: layout_check - selector: layout_count - expectation: - min_count: 2 ---- -schema_version: "1.0" -id: deck.font-policy -scope: deck -tier: 1 -title: All fonts in bundled set -description: Every font referenced in the deck must be from the bundled libre font set (Noto, Liberation, Carlito, Caladea). Non-bundled fonts trigger auto-fail per §4.3. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_affected_slides ---- -schema_version: "1.0" -id: deck.has-embedded-media -scope: deck -tier: 1 -title: Deck contains embedded media -description: The deck must contain at least one embedded image/media asset. -kind: image-asset -severity: major -source_of_truth: ooxml -verification: - method: hash_match +{ + "schema_version": "1.0", + "id": "deck.slide-count", + "scope": "deck", + "tier": 1, + "title": "Exactly 20 slides", + "description": "The Level 3 deck contains exactly 20 ordered slides.", + "kind": "structure", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "slide_count", + "expectation": { + "exact_count": 20 + } + }, + "assertion_id": "deck.assert-slide-count", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.master-present", + "scope": "deck", + "tier": 1, + "title": "AcidSlide master exists", + "description": "At least one native slide master must own the shared background and footer elements.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_count", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "deck.assert-master-present", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.font-policy", + "scope": "deck", + "tier": 1, + "title": "Only bundled fonts render", + "description": "All rendered text uses the bundled font inventory.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_affected_slides", + "affected_slides": { + "status": "complete", + "mode": "named_selector", + "slides": [], + "selector_id": "acidslide.affected-slides.non-bundled-font.v1", + "selector_sha256": "sha256:8cf69d05eb33b14a0f72ef56ca0551f0eda84748a6bb3aaa8e56f46ddb7a10f1" + } + }, + "assertion_id": "deck.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.no-notes", + "scope": "deck", + "tier": 1, + "title": "No notes or comments", + "description": "The package contains no speaker notes or comments.", + "kind": "structure", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "no_notes" + }, + "failure_mode": { + "automatic_fail_if": [ + "notes_or_comments_present" + ], + "propagation": "zero_affected_slides", + "affected_slides": { + "status": "complete", + "mode": "named_selector", + "slides": [], + "selector_id": "acidslide.affected-slides.notes-comments.v1", + "selector_sha256": "sha256:8a1a47d7df727a1c1919ef463d638332f0b6786b05f783ae67e7039e958ab45c" + } + }, + "assertion_id": "deck.assert-no-notes", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.layouts-defined", + "scope": "deck", + "tier": 1, + "title": "Four canonical layouts", + "description": "Title Slide, Content Slide, Two-Column, and Blank with Footer layouts are defined.", + "kind": "master-layout", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "layout_count", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "deck.assert-layouts-defined", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.approved-assets", + "scope": "deck", + "tier": 1, + "title": "Approved media inventory", + "description": "Every required benchmark asset hash occurs in embedded media and no unapproved external media is introduced.", + "kind": "image-asset", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "hash_match", + "selector": "asset_manifest", + "expectation": { + "asset_hashes": { + "hero-abstract": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007", + "cityscape": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "texture-pattern": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385" + } + } + }, + "assertion_id": "deck.assert-approved-assets", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.native-slide-numbers", + "scope": "deck", + "tier": 1, + "title": "Slide numbers are inherited fields", + "description": "Slide numbers originate in the master/layout field rather than copied local text.", + "kind": "fields", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_count", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "deck.assert-native-slide-numbers", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.ordered-tier-prefix", + "scope": "deck", + "tier": 1, + "title": "Tier slide order is stable", + "description": "Level 1 and Level 2 remain ordered prefixes of the 20-slide Level 3 deck.", + "kind": "structure", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "slide_count", + "expectation": { + "exact_count": 20 + } + }, + "assertion_id": "deck.assert-ordered-tier-prefix", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.theme-structure", + "scope": "deck", + "tier": 2, + "title": "Theme references remain semantic", + "description": "Theme-driven colors and local overrides remain distinct in OOXML across the deck.", + "kind": "theme-consistency", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_count", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "deck.assert-theme-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.native-object-coverage", + "scope": "deck", + "tier": 2, + "title": "Native construct coverage", + "description": "The deck contains native charts, tables, fields, connectors, groups, placeholders, and pictures where prompted.", + "kind": "structure", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "slide_count", + "expectation": { + "exact_count": 20 + } + }, + "assertion_id": "deck.assert-native-object-coverage", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.rtl-cjk-coverage", + "scope": "deck", + "tier": 2, + "title": "RTL and CJK coverage", + "description": "Arabic RTL and Japanese CJK content remain editable and correctly encoded.", + "kind": "multilingual", + "severity": "major", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "slide_count", + "expectation": { + "exact_count": 20 + } + }, + "assertion_id": "deck.assert-rtl-cjk-coverage", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.render-consistency", + "scope": "deck", + "tier": 1, + "title": "Deck-wide render consistency", + "description": "All slide exports pass the official SSIM threshold against their corresponding gold exports.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "deck.assert-render-consistency", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.master-visual-consistency", + "scope": "deck", + "tier": 1, + "title": "Inherited footer renders consistently", + "description": "The shared footer line, company label, and slide number align identically across applicable slides.", + "kind": "theme-consistency", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "footer" + } + }, + "assertion_id": "deck.assert-master-visual-consistency", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.palette-consistency", + "scope": "deck", + "tier": 1, + "title": "Deck palette is coherent", + "description": "Repeated palette roles render consistently across all 20 slides.", + "kind": "theme-consistency", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "deck.assert-palette-consistency", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.typography-consistency", + "scope": "deck", + "tier": 1, + "title": "Deck typography is coherent", + "description": "Repeated type roles render with the same family, size, weight, and color throughout the deck.", + "kind": "typography", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "deck.assert-typography-consistency", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.spacing-consistency", + "scope": "deck", + "tier": 2, + "title": "Deck spacing is coherent", + "description": "Repeated margins, gutters, and title anchors align across slide layouts.", + "kind": "spacing-autofit", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "spacing" + } + }, + "assertion_id": "deck.assert-spacing-consistency", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.cross-slide-hierarchy", + "scope": "deck", + "tier": 3, + "title": "Cross-slide hierarchy matches", + "description": "Title, body, focal, and footer hierarchy remains structurally and visually consistent.", + "kind": "theme-consistency", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "layout_check", + "selector": "master_count", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "deck.assert-cross-slide-hierarchy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.line-weight-detail", + "scope": "deck", + "tier": 3, + "title": "Repeated line weights match", + "description": "Master rules, separators, borders, and connectors use the specified weights.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "line_weights" + } + }, + "assertion_id": "deck.assert-line-weight-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.effect-detail", + "scope": "deck", + "tier": 3, + "title": "Repeated effects match", + "description": "Shadows, transparency, gradients, and patterns render consistently where repeated.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "effects" + } + }, + "assertion_id": "deck.assert-effect-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "deck.alignment-detail", + "scope": "deck", + "tier": 3, + "title": "Repeated alignment anchors match", + "description": "Common title, footer, and grid anchors remain aligned throughout the deck.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "all_slides", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "alignment" + } + }, + "assertion_id": "deck.assert-alignment-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-01.yaml b/acidslide-v1/benchmark/checklist/slides/slide-01.yaml index 9311680..f4446cc 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-01.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-01.yaml @@ -1,84 +1,446 @@ -schema_version: "1.0" -id: slide-01.title-placeholder -scope: slide -slide: 1 -tier: 1 -title: Title placeholder present -description: Slide 1 must use a native title placeholder (), not a freestanding text box. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-01.key-text", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `AcidSlide v1` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "AcidSlide v1" + } + }, + "assertion_id": "slide-01.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-01.subtitle-placeholder -scope: slide -slide: 1 -tier: 1 -title: Subtitle or body placeholder present -description: Slide 1 cover must have a subtitle/body placeholder for the secondary text. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: subTitle - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-01.native-primary", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one approved hero image with a 20% left crop; raster or shape imitations do not qualify.", + "kind": "image-asset", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "hash_match", + "selector": "approved_asset", + "expectation": { + "asset_id": "hero-abstract", + "sha256": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007" + } + }, + "assertion_id": "slide-01.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-01.hero-image -scope: slide -slide: 1 -tier: 1 -title: Hero image present -description: Slide 1 must contain exactly one precisely cropped hero image. -kind: image-asset -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: picture - expectation: - exact_count: 1 - required: true +{ + "schema_version": "1.0", + "id": "slide-01.layout-binding", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Title Slide layout binding", + "description": "The slide must be bound to the `Title Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-01.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-01.decorative-shapes -scope: slide -slide: 1 -tier: 1 -title: Decorative shapes with effects -description: Slide 1 should have overlapping decorative shapes with shadow and/or transparency. -kind: structure -severity: minor -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 2 +{ + "schema_version": "1.0", + "id": "slide-01.font-policy", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 1 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-01.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-01.font-policy -scope: slide -slide: 1 -tier: 1 -title: Font policy compliance -description: All fonts on slide 1 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-01.composition", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Required composition inventory", + "description": "The slide composition must include three overlapping translucent rounded rectangles.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-01.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.full-slide-fidelity", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-01.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.focal-fidelity", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the right-half hero image and title lockup; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the right-half hero image and title lockup" + } + }, + "assertion_id": "slide-01.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.hierarchy-z-order", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Hierarchy and z-order semantics", + "description": "Preserve the specified Rectangle C, Rectangle A, hero, Rectangle B, title, subtitle z-order in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-01.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.semantic-structure", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one approved hero image with a 20% left crop while remaining visually equivalent to the reference.", + "kind": "image-asset", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "picture", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-01.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.palette", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-01.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.typography", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-01.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.spacing", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-01.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-01.decorative-detail", + "scope": "slide", + "slide": 1, + "tier": 1, + "title": "Decorative and effect details", + "description": "Preserve the hero outer shadow and rounded-rectangle transparency as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-01.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-02.yaml b/acidslide-v1/benchmark/checklist/slides/slide-02.yaml index e2362fb..495155b 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-02.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-02.yaml @@ -1,67 +1,446 @@ -schema_version: "1.0" -id: slide-02.title-placeholder -scope: slide -slide: 2 -tier: 1 -title: Title placeholder present -description: Slide 2 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-02.key-text", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Agenda` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Agenda" + } + }, + "assertion_id": "slide-02.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-02.body-placeholder -scope: slide -slide: 2 -tier: 1 -title: Body placeholder present -description: Slide 2 agenda must use a native body placeholder for bulleted content. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: body - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-02.native-primary", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one native group containing the three icon-time rows; raster or shape imitations do not qualify.", + "kind": "grouping", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 1, + "required": true + } + }, + "assertion_id": "slide-02.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-02.grouped-rows -scope: slide -slide: 2 -tier: 1 -title: Grouped icon-text rows -description: Agenda items should be grouped (icon + text as grouped objects). -kind: grouping -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: group - expectation: - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-02.layout-binding", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-02.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-02.font-policy -scope: slide -slide: 2 -tier: 1 -title: Font policy compliance -description: All fonts on slide 2 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-02.font-policy", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 2 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-02.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.composition", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Required composition inventory", + "description": "The slide composition must include the agenda placeholder plus three circle/time rows.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 7 + } + }, + "assertion_id": "slide-02.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.full-slide-fidelity", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-02.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.focal-fidelity", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the agenda body and aligned time column; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the agenda body and aligned time column" + } + }, + "assertion_id": "slide-02.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.hierarchy-z-order", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Hierarchy and z-order semantics", + "description": "Preserve two bullet levels and the grouped time-column relationship in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 7 + } + }, + "assertion_id": "slide-02.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.semantic-structure", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one native group containing the three icon-time rows while remaining visually equivalent to the reference.", + "kind": "grouping", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-02.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.palette", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-02.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.typography", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-02.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.spacing", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-02.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-02.decorative-detail", + "scope": "slide", + "slide": 2, + "tier": 1, + "title": "Decorative and effect details", + "description": "Preserve bullet indents, line spacing, and paragraph spacing as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 7 + } + }, + "assertion_id": "slide-02.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-03.yaml b/acidslide-v1/benchmark/checklist/slides/slide-03.yaml index 64f1b85..1305138 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-03.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-03.yaml @@ -1,59 +1,445 @@ -schema_version: "1.0" -id: slide-03.native-table-required -scope: slide -slide: 3 -tier: 1 -title: Native table required -description: Slide 3 must contain exactly one native OOXML table (). -kind: table -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: table - expectation: - exact_count: 1 - required: true - tolerance: - bbox_px: 2 - units: pixels_at_1920x1080 -failure_mode: - automatic_fail_if: - - grouped_lines_and_text_used_as_table - - raster_image_used_as_table - propagation: zero_slide ---- -schema_version: "1.0" -id: slide-03.title-placeholder -scope: slide -slide: 3 -tier: 1 -title: Title placeholder present -description: Slide 3 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 ---- -schema_version: "1.0" -id: slide-03.font-policy -scope: slide -slide: 3 -tier: 1 -title: Font policy compliance -description: All fonts on slide 3 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-03.key-text", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Performance Metrics` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Performance Metrics" + } + }, + "assertion_id": "slide-03.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.native-primary", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one native 7-by-5 OOXML table; raster or shape imitations do not qualify.", + "kind": "table", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1, + "required": true + } + }, + "assertion_id": "slide-03.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.layout-binding", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-03.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.font-policy", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 3 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-03.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.composition", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Required composition inventory", + "description": "The slide composition must include the native table, annotation callout, and connector.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-03.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.full-slide-fidelity", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-03.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.focal-fidelity", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the full metrics table and throughput callout; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the full metrics table and throughput callout" + } + }, + "assertion_id": "slide-03.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.hierarchy-z-order", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Hierarchy and z-order semantics", + "description": "Preserve header, alternating rows, conditional target colors, and mixed border weights in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-03.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.semantic-structure", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one native 7-by-5 OOXML table while remaining visually equivalent to the reference.", + "kind": "table", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-03.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.palette", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-03.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.typography", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-03.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.spacing", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-03.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-03.decorative-detail", + "scope": "slide", + "slide": 3, + "tier": 1, + "title": "Decorative and effect details", + "description": "Preserve cell padding and the 0.5cm paragraph indent as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-03.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-04.yaml b/acidslide-v1/benchmark/checklist/slides/slide-04.yaml index e530d0a..ac355fa 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-04.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-04.yaml @@ -1,72 +1,446 @@ -schema_version: "1.0" -id: slide-04.native-chart-required -scope: slide -slide: 4 -tier: 1 -title: Native chart required -description: Slide 4 must contain exactly one native OOXML chart ( with embedded xlsx). -kind: chart -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: chart - expectation: - exact_count: 1 - required: true -failure_mode: - automatic_fail_if: - - raster_image_used_as_chart - - shapes_used_as_chart - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-04.key-text", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Revenue Growth` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Revenue Growth" + } + }, + "assertion_id": "slide-04.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-04.title-placeholder -scope: slide -slide: 4 -tier: 1 -title: Title placeholder present -description: Slide 4 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-04.native-primary", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one native clustered horizontal bar chart with the supplied data; raster or shape imitations do not qualify.", + "kind": "chart", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1, + "required": true + } + }, + "assertion_id": "slide-04.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-04.callout-shapes -scope: slide -slide: 4 -tier: 1 -title: Overlaid callout shapes -description: Chart slide should have callout annotation shapes overlaid on or near the chart. -kind: structure -severity: minor -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-04.layout-binding", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-04.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-04.font-policy -scope: slide -slide: 4 -tier: 1 -title: Font policy compliance -description: All fonts on slide 4 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-04.font-policy", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 4 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-04.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.composition", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Required composition inventory", + "description": "The slide composition must include the chart, two callouts, connectors, and takeaway block.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-04.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.full-slide-fidelity", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-04.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.focal-fidelity", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the chart plot and overlaid YoY annotations; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the chart plot and overlaid YoY annotations" + } + }, + "assertion_id": "slide-04.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.hierarchy-z-order", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Hierarchy and z-order semantics", + "description": "Preserve the chart-to-callout connector and overlay relationships in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-04.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.semantic-structure", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one native clustered horizontal bar chart with the supplied data while remaining visually equivalent to the reference.", + "kind": "chart", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-04.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.palette", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-04.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.typography", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-04.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.spacing", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-04.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-04.decorative-detail", + "scope": "slide", + "slide": 4, + "tier": 1, + "title": "Decorative and effect details", + "description": "Preserve legend, gridline, axis-label, and transparent-background styling as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-04.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-05.yaml b/acidslide-v1/benchmark/checklist/slides/slide-05.yaml index f786de6..1f7d600 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-05.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-05.yaml @@ -1,47 +1,446 @@ -schema_version: "1.0" -id: slide-05.master-ref -scope: slide -slide: 5 -tier: 1 -title: Layout reference present -description: Slide 5 must reference a slide layout (master reuse enforcement test). -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: master_ref ---- -schema_version: "1.0" -id: slide-05.placeholder-bound -scope: slide -slide: 5 -tier: 1 -title: Placeholder-bound content -description: Slide 5 content must use placeholders inherited from layout, not freestanding text boxes. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - min_count: 1 ---- -schema_version: "1.0" -id: slide-05.font-policy -scope: slide -slide: 5 -tier: 1 -title: Font policy compliance -description: All fonts on slide 5 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-05.key-text", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Our Team` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Our Team" + } + }, + "assertion_id": "slide-05.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.native-primary", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Primary native construct is present", + "description": "The primary structural requirement is three grouped team-member cards; raster or shape imitations do not qualify.", + "kind": "grouping", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 3, + "required": true + } + }, + "assertion_id": "slide-05.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.layout-binding", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-05.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.font-policy", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 5 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-05.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.composition", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Required composition inventory", + "description": "The slide composition must include three equally sized and distributed cards.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 12 + } + }, + "assertion_id": "slide-05.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.full-slide-fidelity", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-05.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.focal-fidelity", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the three-card team composition; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-card team composition" + } + }, + "assertion_id": "slide-05.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.hierarchy-z-order", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Hierarchy and z-order semantics", + "description": "Preserve footer, accent bar, company name, and number inherited rather than copied in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 12 + } + }, + "assertion_id": "slide-05.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.semantic-structure", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express three grouped team-member cards while remaining visually equivalent to the reference.", + "kind": "grouping", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-05.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.palette", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-05.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.typography", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-05.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.spacing", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-05.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-05.decorative-detail", + "scope": "slide", + "slide": 5, + "tier": 1, + "title": "Decorative and effect details", + "description": "Preserve card border, circle, typography, and equal spacing as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 12 + } + }, + "assertion_id": "slide-05.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-06.yaml b/acidslide-v1/benchmark/checklist/slides/slide-06.yaml index 5f72050..40af606 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-06.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-06.yaml @@ -1,50 +1,445 @@ -schema_version: "1.0" -id: slide-06.multilingual-text -scope: slide -slide: 6 -tier: 2 -title: Multilingual text present -description: Slide 6 must contain English, Arabic (RTL), and Japanese (CJK) text runs. -kind: multilingual -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 3 ---- -schema_version: "1.0" -id: slide-06.title-placeholder -scope: slide -slide: 6 -tier: 2 -title: Title placeholder present -description: Slide 6 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 ---- -schema_version: "1.0" -id: slide-06.font-policy -scope: slide -slide: 6 -tier: 2 -title: Font policy compliance -description: All fonts on slide 6 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-06.key-text", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Global Perspectives` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Global Perspectives" + } + }, + "assertion_id": "slide-06.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.native-primary", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is English, Arabic RTL, and Japanese text boxes plus the overlapping callout; raster or shape imitations do not qualify.", + "kind": "multilingual", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4, + "required": true + } + }, + "assertion_id": "slide-06.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.layout-binding", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-06.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.font-policy", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 6 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-06.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.composition", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include three editorial columns, two separators, and one callout.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-06.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.full-slide-fidelity", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-06.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.focal-fidelity", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the three-script editorial region; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-script editorial region" + } + }, + "assertion_id": "slide-06.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.hierarchy-z-order", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve RTL paragraph direction, CJK line breaking, and callout overlap in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-06.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.semantic-structure", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express English, Arabic RTL, and Japanese text boxes plus the overlapping callout while remaining visually equivalent to the reference.", + "kind": "multilingual", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-06.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.palette", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-06.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.typography", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-06.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.spacing", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-06.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-06.decorative-detail", + "scope": "slide", + "slide": 6, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve separator opacity and script-specific font assignment as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-06.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-07.yaml b/acidslide-v1/benchmark/checklist/slides/slide-07.yaml index c6a9a24..00bf986 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-07.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-07.yaml @@ -1,51 +1,445 @@ -schema_version: "1.0" -id: slide-07.multiple-images -scope: slide -slide: 7 -tier: 2 -title: Multiple images with cropping -description: Slide 7 must contain multiple images with different crop rectangles and/or crop-to-shape masking. -kind: image-asset -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: picture - expectation: - min_count: 2 - required: true ---- -schema_version: "1.0" -id: slide-07.title-placeholder -scope: slide -slide: 7 -tier: 2 -title: Title placeholder present -description: Slide 7 must use a native title placeholder. -kind: master-layout -severity: major -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 ---- -schema_version: "1.0" -id: slide-07.font-policy -scope: slide -slide: 7 -tier: 2 -title: Font policy compliance -description: All fonts on slide 7 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-07.key-text", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Image Handling` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Image Handling" + } + }, + "assertion_id": "slide-07.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.native-primary", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is three approved image instances with distinct crops and masks; raster or shape imitations do not qualify.", + "kind": "image-asset", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "hash_match", + "selector": "approved_asset", + "expectation": { + "asset_id": "cityscape", + "sha256": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a" + } + }, + "assertion_id": "slide-07.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.layout-binding", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-07.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.font-policy", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 7 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-07.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.composition", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include three pictures, three captions, title, and PREVIEW overlay.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-07.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.full-slide-fidelity", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-07.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.focal-fidelity", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the three-image crop comparison; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-image crop comparison" + } + }, + "assertion_id": "slide-07.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.hierarchy-z-order", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve the overlay above Image B and the picture-to-caption relationships in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-07.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.semantic-structure", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express three approved image instances with distinct crops and masks while remaining visually equivalent to the reference.", + "kind": "image-asset", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "picture", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-07.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.palette", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-07.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.typography", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-07.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.spacing", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-07.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-07.decorative-detail", + "scope": "slide", + "slide": 7, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve ellipse mask, rounded mask, crops, and italic captions as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-07.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-08.yaml b/acidslide-v1/benchmark/checklist/slides/slide-08.yaml index abd5594..ba4d1da 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-08.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-08.yaml @@ -1,49 +1,445 @@ -schema_version: "1.0" -id: slide-08.shadow-present -scope: slide -slide: 8 -tier: 2 -title: Shadow effects present -description: Slide 8 must contain shapes with shadow effects (outerShdw or innerShdw). -kind: structure -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 2 ---- -schema_version: "1.0" -id: slide-08.gradient-fill -scope: slide -slide: 8 -tier: 2 -title: Gradient fills present -description: Slide 8 should contain gradient fill effects. -kind: gradient-pattern -severity: minor -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 1 ---- -schema_version: "1.0" -id: slide-08.font-policy -scope: slide -slide: 8 -tier: 2 -title: Font policy compliance -description: All fonts on slide 8 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-08.key-text", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Depth & Layering` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Depth & Layering" + } + }, + "assertion_id": "slide-08.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.native-primary", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is two selective groups containing the five cards; raster or shape imitations do not qualify.", + "kind": "grouping", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 2, + "required": true + } + }, + "assertion_id": "slide-08.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.layout-binding", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-08.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.font-policy", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 8 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-08.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.composition", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include five cards plus one full-width gradient strip.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-08.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.full-slide-fidelity", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-08.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.focal-fidelity", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the cascading five-card stack; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the cascading five-card stack" + } + }, + "assertion_id": "slide-08.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.hierarchy-z-order", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve Card 1 through Card 5 z-order with only the requested subgrouping in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-08.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.semantic-structure", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express two selective groups containing the five cards while remaining visually equivalent to the reference.", + "kind": "grouping", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-08.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.palette", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-08.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.typography", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-08.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.spacing", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-08.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-08.decorative-detail", + "scope": "slide", + "slide": 8, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve per-card opacity, outer shadow, and bottom gradient as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-08.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-09.yaml b/acidslide-v1/benchmark/checklist/slides/slide-09.yaml index 71adeaf..8d47a06 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-09.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-09.yaml @@ -1,51 +1,446 @@ -schema_version: "1.0" -id: slide-09.dense-text -scope: slide -slide: 9 -tier: 2 -title: Dense text content present -description: Slide 9 must contain high-density text content testing overflow behavior. -kind: overflow -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 3 ---- -schema_version: "1.0" -id: slide-09.no-full-slide-raster -scope: slide -slide: 9 -tier: 2 -title: No full-slide raster cheat -description: No single image may cover more than 40% of slide area. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: no_full_slide_raster -failure_mode: - automatic_fail_if: - - full_slide_raster_detected - propagation: zero_slide ---- -schema_version: "1.0" -id: slide-09.font-policy -scope: slide -slide: 9 -tier: 2 -title: Font policy compliance -description: All fonts on slide 9 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-09.key-text", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `API Reference` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "API Reference" + } + }, + "assertion_id": "slide-09.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.native-primary", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is two dense monospaced text boxes with different autofit modes; raster or shape imitations do not qualify.", + "kind": "overflow", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2, + "required": true + } + }, + "assertion_id": "slide-09.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.layout-binding", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-09.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.font-policy", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 9 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-09.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.composition", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include two code columns and their labels.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-09.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.full-slide-fidelity", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-09.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.focal-fidelity", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the paired fixed-size and auto-shrink columns; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the paired fixed-size and auto-shrink columns" + } + }, + "assertion_id": "slide-09.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.hierarchy-z-order", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve left clipping versus right auto-shrink semantics in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-09.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.semantic-structure", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express two dense monospaced text boxes with different autofit modes while remaining visually equivalent to the reference.", + "kind": "overflow", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-09.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.palette", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-09.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.typography", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-09.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.spacing", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-09.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-09.decorative-detail", + "scope": "slide", + "slide": 9, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve 1.15 line spacing and exact indentation as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-09.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-10.yaml b/acidslide-v1/benchmark/checklist/slides/slide-10.yaml index 79d0026..9efea0f 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-10.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-10.yaml @@ -1,50 +1,445 @@ -schema_version: "1.0" -id: slide-10.connectors-present -scope: slide -slide: 10 -tier: 2 -title: Native connectors present -description: Slide 10 must use native connector shapes (cxnSp), not drawn lines. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: connector - expectation: - min_count: 1 - required: true ---- -schema_version: "1.0" -id: slide-10.grouped-labels -scope: slide -slide: 10 -tier: 2 -title: Grouped labels present -description: Diagram labels should be grouped with their associated shapes. -kind: grouping -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: group - expectation: - min_count: 1 ---- -schema_version: "1.0" -id: slide-10.font-policy -scope: slide -slide: 10 -tier: 2 -title: Font policy compliance -description: All fonts on slide 10 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-10.key-text", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `System Architecture` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "System Architecture" + } + }, + "assertion_id": "slide-10.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.native-primary", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is seven native connectors with destination arrowheads; raster or shape imitations do not qualify.", + "kind": "structure", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "connector", + "expectation": { + "min_count": 7, + "required": true + } + }, + "assertion_id": "slide-10.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.layout-binding", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-10.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.font-policy", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 10 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-10.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.composition", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include three nested groups covering processing, persistence, and backend.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-10.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.full-slide-fidelity", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-10.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.focal-fidelity", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the centered architecture network; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the centered architecture network" + } + }, + "assertion_id": "slide-10.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.hierarchy-z-order", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve connector attachment, routing, and three-level backend grouping in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-10.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.semantic-structure", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express seven native connectors with destination arrowheads while remaining visually equivalent to the reference.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "connector", + "expectation": { + "min_count": 7 + } + }, + "assertion_id": "slide-10.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.palette", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-10.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.typography", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-10.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.spacing", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-10.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-10.decorative-detail", + "scope": "slide", + "slide": 10, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve dashed group borders and connector labels as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-10.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-11.yaml b/acidslide-v1/benchmark/checklist/slides/slide-11.yaml index bfdd732..6a0c5cf 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-11.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-11.yaml @@ -1,33 +1,446 @@ -schema_version: "1.0" -id: slide-11.theme-consistency -scope: slide -slide: 11 -tier: 2 -title: Theme color references present -description: Some elements must reference theme colors (schemeClr), testing theme vs local override behavior. -kind: theme-consistency -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 2 ---- -schema_version: "1.0" -id: slide-11.font-policy -scope: slide -slide: 11 -tier: 2 -title: Font policy compliance -description: All fonts on slide 11 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-11.key-text", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Brand Colors` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Brand Colors" + } + }, + "assertion_id": "slide-11.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.native-primary", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is six swatches split between theme references and explicit RGB overrides; raster or shape imitations do not qualify.", + "kind": "theme-consistency", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6, + "required": true + } + }, + "assertion_id": "slide-11.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.layout-binding", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-11.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.font-policy", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 11 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-11.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.composition", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include six swatches, six labels, and explanatory copy.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-11.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.full-slide-fidelity", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-11.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.focal-fidelity", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the two-row swatch comparison; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the two-row swatch comparison" + } + }, + "assertion_id": "slide-11.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.hierarchy-z-order", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve theme scheme colors in the top row versus fixed sRGB values below in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-11.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.semantic-structure", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express six swatches split between theme references and explicit RGB overrides while remaining visually equivalent to the reference.", + "kind": "theme-consistency", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-11.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.palette", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-11.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.typography", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-11.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.spacing", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-11.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-11.decorative-detail", + "scope": "slide", + "slide": 11, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve swatch sizing, label color, and row spacing as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-11.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-12.yaml b/acidslide-v1/benchmark/checklist/slides/slide-12.yaml index 22e9c7f..b041d51 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-12.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-12.yaml @@ -1,66 +1,446 @@ -schema_version: "1.0" -id: slide-12.slidenum-field -scope: slide -slide: 12 -tier: 2 -title: Slide number field present -description: Slide 12 must contain a native slide number field ( with slidenum type). -kind: fields -severity: critical -source_of_truth: ooxml -verification: - method: field_check - expectation: - field_type: slidenum +{ + "schema_version": "1.0", + "id": "slide-12.key-text", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Document Fields` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Document Fields" + } + }, + "assertion_id": "slide-12.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-12.title-placeholder -scope: slide -slide: 12 -tier: 2 -title: Title placeholder present -description: Slide 12 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-12.native-primary", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Primary native construct is present", + "description": "The primary structural requirement is native slide-number and fixed date/time fields; raster or shape imitations do not qualify.", + "kind": "fields", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "field", + "expectation": { + "min_count": 2, + "required": true + } + }, + "assertion_id": "slide-12.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-12.body-placeholder -scope: slide -slide: 12 -tier: 2 -title: Body placeholder present -description: Slide 12 must use a native body placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: body - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-12.layout-binding", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-12.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-12.font-policy -scope: slide -slide: 12 -tier: 2 -title: Font policy compliance -description: All fonts on slide 12 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-12.font-policy", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 12 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-12.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.composition", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Required composition inventory", + "description": "The slide composition must include three field demonstrations, labels, and static comparison.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-12.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.full-slide-fidelity", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-12.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.focal-fidelity", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the field demonstration stack; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the field demonstration stack" + } + }, + "assertion_id": "slide-12.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.hierarchy-z-order", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Hierarchy and z-order semantics", + "description": "Preserve live field runs and master footer versus static comparison text in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-12.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.semantic-structure", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express native slide-number and fixed date/time fields while remaining visually equivalent to the reference.", + "kind": "fields", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "field", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-12.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.palette", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-12.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.typography", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-12.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.spacing", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-12.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-12.decorative-detail", + "scope": "slide", + "slide": 12, + "tier": 2, + "title": "Decorative and effect details", + "description": "Preserve field labels, comparison alignment, and footer placement as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-12.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-13.yaml b/acidslide-v1/benchmark/checklist/slides/slide-13.yaml index db91931..d7495c3 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-13.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-13.yaml @@ -1,76 +1,445 @@ -schema_version: "1.0" -id: slide-13.native-chart -scope: slide -slide: 13 -tier: 3 -title: Native chart present -description: Composite slide 13 must contain a native chart. -kind: chart -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: chart - expectation: - exact_count: 1 - required: true -failure_mode: - automatic_fail_if: - - raster_image_used_as_chart - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-13.key-text", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Composite Stress` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Composite Stress" + } + }, + "assertion_id": "slide-13.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-13.native-table -scope: slide -slide: 13 -tier: 3 -title: Native table present -description: Composite slide 13 must contain a native table. -kind: table -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: table - expectation: - exact_count: 1 - required: true -failure_mode: - automatic_fail_if: - - grouped_lines_and_text_used_as_table - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-13.native-primary", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one native six-segment pie chart; raster or shape imitations do not qualify.", + "kind": "chart", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1, + "required": true + } + }, + "assertion_id": "slide-13.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-13.image-present -scope: slide -slide: 13 -tier: 3 -title: Image present -description: Composite slide 13 must contain at least one embedded image. -kind: image-asset -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: picture - expectation: - min_count: 1 - required: true +{ + "schema_version": "1.0", + "id": "slide-13.layout-binding", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-13.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-13.font-policy -scope: slide -slide: 13 -tier: 3 -title: Font policy compliance -description: All fonts on slide 13 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-13.font-policy", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 13 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-13.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.composition", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include a native chart, native table, approved image, Arabic annotation, and three callouts.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-13.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.full-slide-fidelity", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-13.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.focal-fidelity", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the chart-table-image composite; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the chart-table-image composite" + } + }, + "assertion_id": "slide-13.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.hierarchy-z-order", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve callouts layered over the composite without obscuring data in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-13.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.semantic-structure", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one native six-segment pie chart while remaining visually equivalent to the reference.", + "kind": "chart", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-13.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.palette", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-13.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.typography", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-13.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.spacing", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-13.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-13.decorative-detail", + "scope": "slide", + "slide": 13, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve chart labels, table borders, image crop, and annotation styling as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-13.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-14.yaml b/acidslide-v1/benchmark/checklist/slides/slide-14.yaml index 24cceaf..84bd84d 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-14.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-14.yaml @@ -1,33 +1,446 @@ -schema_version: "1.0" -id: slide-14.rtl-text -scope: slide -slide: 14 -tier: 3 -title: RTL text blocks present -description: Slide 14 must contain Arabic RTL text with stronger emphasis than slide 6. -kind: multilingual -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 3 ---- -schema_version: "1.0" -id: slide-14.font-policy -scope: slide -slide: 14 -tier: 3 -title: Font policy compliance -description: All fonts on slide 14 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-14.key-text", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `RTL Systems Review` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "RTL Systems Review" + } + }, + "assertion_id": "slide-14.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.native-primary", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is two long-form text columns containing Arabic, English, and bidirectional runs; raster or shape imitations do not qualify.", + "kind": "multilingual", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2, + "required": true + } + }, + "assertion_id": "slide-14.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.layout-binding", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Two-Column layout binding", + "description": "The slide must be bound to the `Two-Column` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-14.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.font-policy", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 14 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-14.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.composition", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include two mirrored editorial columns plus title and divider.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-14.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.full-slide-fidelity", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-14.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.focal-fidelity", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the Arabic-heavy left and English right comparison; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the Arabic-heavy left and English right comparison" + } + }, + "assertion_id": "slide-14.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.hierarchy-z-order", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve native RTL direction and correct bidirectional run order in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-14.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.semantic-structure", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express two long-form text columns containing Arabic, English, and bidirectional runs while remaining visually equivalent to the reference.", + "kind": "multilingual", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 2 + } + }, + "assertion_id": "slide-14.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.palette", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-14.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.typography", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-14.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.spacing", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-14.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-14.decorative-detail", + "scope": "slide", + "slide": 14, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve mirrored padding, divider, and script-specific typography as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 4 + } + }, + "assertion_id": "slide-14.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-15.yaml b/acidslide-v1/benchmark/checklist/slides/slide-15.yaml index d300291..3a066e3 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-15.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-15.yaml @@ -1,33 +1,445 @@ -schema_version: "1.0" -id: slide-15.rotated-text -scope: slide -slide: 15 -tier: 3 -title: Rotated text boxes present -description: Slide 15 must contain text boxes with non-zero rotation (). -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 1 ---- -schema_version: "1.0" -id: slide-15.font-policy -scope: slide -slide: 15 -tier: 3 -title: Font policy compliance -description: All fonts on slide 15 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-15.key-text", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Rotation Atlas` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Rotation Atlas" + } + }, + "assertion_id": "slide-15.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.native-primary", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is five text boxes and five supporting shapes at the specified rotations; raster or shape imitations do not qualify.", + "kind": "structure", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 10, + "required": true + } + }, + "assertion_id": "slide-15.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.layout-binding", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-15.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.font-policy", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 15 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-15.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.composition", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include five label-and-shape pairs across a shared alignment grid.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 10 + } + }, + "assertion_id": "slide-15.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.full-slide-fidelity", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-15.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.focal-fidelity", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the five-angle rotation sequence; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the five-angle rotation sequence" + } + }, + "assertion_id": "slide-15.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.hierarchy-z-order", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve text and supporting shapes sharing exact rotation and anchor centers in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 10 + } + }, + "assertion_id": "slide-15.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.semantic-structure", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express five text boxes and five supporting shapes at the specified rotations while remaining visually equivalent to the reference.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 10 + } + }, + "assertion_id": "slide-15.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.palette", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-15.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.typography", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-15.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.spacing", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-15.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-15.decorative-detail", + "scope": "slide", + "slide": 15, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve rotation angles, anchor points, and line alignment as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 10 + } + }, + "assertion_id": "slide-15.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-16.yaml b/acidslide-v1/benchmark/checklist/slides/slide-16.yaml index 55c23db..89f11b5 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-16.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-16.yaml @@ -1,33 +1,445 @@ -schema_version: "1.0" -id: slide-16.off-canvas-objects -scope: slide -slide: 16 -tier: 3 -title: Objects present (off-canvas bleed test) -description: Slide 16 must contain objects, some of which intentionally extend beyond the canvas boundary. -kind: structure -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 2 ---- -schema_version: "1.0" -id: slide-16.font-policy -scope: slide -slide: 16 -tier: 3 -title: Font policy compliance -description: All fonts on slide 16 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-16.key-text", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Beyond the Frame` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Beyond the Frame" + } + }, + "assertion_id": "slide-16.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.native-primary", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is three intentional bleed objects extending past left, top, and right edges; raster or shape imitations do not qualify.", + "kind": "structure", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3, + "required": true + } + }, + "assertion_id": "slide-16.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.layout-binding", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-16.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.font-policy", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 16 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-16.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.composition", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include off-canvas circle, right-bleed rectangle, title, and two on-canvas labels.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-16.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.full-slide-fidelity", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-16.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.focal-fidelity", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the visible portions of the bleed objects; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the visible portions of the bleed objects" + } + }, + "assertion_id": "slide-16.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.hierarchy-z-order", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve intentional negative coordinates retained without hidden-content cheating in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-16.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.semantic-structure", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express three intentional bleed objects extending past left, top, and right edges while remaining visually equivalent to the reference.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-16.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.palette", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-16.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.typography", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-16.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.spacing", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-16.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-16.decorative-detail", + "scope": "slide", + "slide": 16, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve edge clipping, opacity, and on-canvas label spacing as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-16.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-17.yaml b/acidslide-v1/benchmark/checklist/slides/slide-17.yaml index 75c8332..aaefefa 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-17.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-17.yaml @@ -1,34 +1,445 @@ -schema_version: "1.0" -id: slide-17.deep-grouping -scope: slide -slide: 17 -tier: 3 -title: Nested groups present -description: Slide 17 must contain nested group shapes (groups inside groups). -kind: grouping -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: group - expectation: - min_count: 2 - required: true ---- -schema_version: "1.0" -id: slide-17.font-policy -scope: slide -slide: 17 -tier: 3 -title: Font policy compliance -description: All fonts on slide 17 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-17.key-text", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Nested Systems` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Nested Systems" + } + }, + "assertion_id": "slide-17.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.native-primary", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is at least six group objects spanning three nested levels; raster or shape imitations do not qualify.", + "kind": "grouping", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 6, + "required": true + } + }, + "assertion_id": "slide-17.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.layout-binding", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-17.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.font-policy", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 17 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-17.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.composition", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include three hierarchy levels with 18 or more leaf shapes.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 18 + } + }, + "assertion_id": "slide-17.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.full-slide-fidelity", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-17.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.focal-fidelity", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the centered nested-group assembly; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the centered nested-group assembly" + } + }, + "assertion_id": "slide-17.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.hierarchy-z-order", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve outer, middle, and inner group transforms with preserved z-order in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 18 + } + }, + "assertion_id": "slide-17.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.semantic-structure", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express at least six group objects spanning three nested levels while remaining visually equivalent to the reference.", + "kind": "grouping", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "group", + "expectation": { + "min_count": 6 + } + }, + "assertion_id": "slide-17.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.palette", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-17.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.typography", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-17.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.spacing", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-17.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-17.decorative-detail", + "scope": "slide", + "slide": 17, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve group borders, internal spacing, and label alignment as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 18 + } + }, + "assertion_id": "slide-17.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-18.yaml b/acidslide-v1/benchmark/checklist/slides/slide-18.yaml index 3d0153c..40d6270 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-18.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-18.yaml @@ -1,33 +1,445 @@ -schema_version: "1.0" -id: slide-18.multi-column-layout -scope: slide -slide: 18 -tier: 3 -title: Multi-column layout with text -description: Slide 18 must contain multiple text blocks arranged in a column layout with images. -kind: structure -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 4 ---- -schema_version: "1.0" -id: slide-18.font-policy -scope: slide -slide: 18 -tier: 3 -title: Font policy compliance -description: All fonts on slide 18 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-18.key-text", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Three Cities / 三つの都市` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Three Cities / 三つの都市" + } + }, + "assertion_id": "slide-18.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.native-primary", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is three approved header-image instances, one per editorial column; raster or shape imitations do not qualify.", + "kind": "image-asset", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "hash_match", + "selector": "approved_asset", + "expectation": { + "asset_id": "texture-pattern", + "sha256": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385" + } + }, + "assertion_id": "slide-18.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.layout-binding", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-18.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.font-policy", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 18 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-18.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.composition", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include three columns with images, body copy, and pull quotes.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-18.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.full-slide-fidelity", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-18.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.focal-fidelity", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the magazine-style three-column spread; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the magazine-style three-column spread" + } + }, + "assertion_id": "slide-18.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.hierarchy-z-order", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve column-local image, copy, and quote relationships in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-18.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.semantic-structure", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express three approved header-image instances, one per editorial column while remaining visually equivalent to the reference.", + "kind": "image-asset", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "picture", + "expectation": { + "min_count": 3 + } + }, + "assertion_id": "slide-18.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.palette", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-18.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.typography", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-18.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.spacing", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-18.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-18.decorative-detail", + "scope": "slide", + "slide": 18, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve the patterned center column and consistent gutters as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 9 + } + }, + "assertion_id": "slide-18.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-19.yaml b/acidslide-v1/benchmark/checklist/slides/slide-19.yaml index b894dae..b690775 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-19.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-19.yaml @@ -1,67 +1,446 @@ -schema_version: "1.0" -id: slide-19.title-placeholder -scope: slide -slide: 19 -tier: 3 -title: Title placeholder present -description: Slide 19 must use a native title placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: title - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-19.key-text", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `Design System Audit` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "Design System Audit" + } + }, + "assertion_id": "slide-19.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-19.body-placeholder -scope: slide -slide: 19 -tier: 3 -title: Body placeholder present -description: Slide 19 must use a native body placeholder. -kind: master-layout -severity: critical -source_of_truth: ooxml -verification: - method: layout_check - selector: placeholder - expectation: - placeholder_type: body - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-19.native-primary", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is five repeated design-system samples including two internal hyperlinks; raster or shape imitations do not qualify.", + "kind": "theme-consistency", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5, + "required": true + } + }, + "assertion_id": "slide-19.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-19.consistency-shapes -scope: slide -slide: 19 -tier: 3 -title: Repeated elements for consistency -description: Slide 19 should contain repeated elements matching the rest of the deck. -kind: structure -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: shape - expectation: - min_count: 2 +{ + "schema_version": "1.0", + "id": "slide-19.layout-binding", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Content Slide layout binding", + "description": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "placeholder", + "expectation": { + "placeholder_type": "title", + "min_count": 1 + } + }, + "assertion_id": "slide-19.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-19.font-policy -scope: slide -slide: 19 -tier: 3 -title: Font policy compliance -description: All fonts on slide 19 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-19.font-policy", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 19 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-19.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.composition", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include master-accurate samples for typography, colors, spacing, lines, and navigation.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 8 + } + }, + "assertion_id": "slide-19.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.full-slide-fidelity", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-19.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.focal-fidelity", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the design-token audit grid; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the design-token audit grid" + } + }, + "assertion_id": "slide-19.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.hierarchy-z-order", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve internal links target Slides 1 and 5 while master elements remain inherited in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 8 + } + }, + "assertion_id": "slide-19.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.semantic-structure", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express five repeated design-system samples including two internal hyperlinks while remaining visually equivalent to the reference.", + "kind": "theme-consistency", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 5 + } + }, + "assertion_id": "slide-19.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.palette", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-19.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.typography", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-19.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.spacing", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-19.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-19.decorative-detail", + "scope": "slide", + "slide": 19, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve exact token values and equal sample spacing as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "shape", + "expectation": { + "min_count": 8 + } + }, + "assertion_id": "slide-19.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/checklist/slides/slide-20.yaml b/acidslide-v1/benchmark/checklist/slides/slide-20.yaml index 2fa9b70..b80393b 100644 --- a/acidslide-v1/benchmark/checklist/slides/slide-20.yaml +++ b/acidslide-v1/benchmark/checklist/slides/slide-20.yaml @@ -1,92 +1,445 @@ -schema_version: "1.0" -id: slide-20.native-chart -scope: slide -slide: 20 -tier: 3 -title: Native chart present -description: Final torture slide must contain a native chart. -kind: chart -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: chart - expectation: - exact_count: 1 - required: true -failure_mode: - automatic_fail_if: - - raster_image_used_as_chart - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-20.key-text", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Required key text is present", + "description": "The slide must preserve the exact key text `AcidSlide Synthesis` as editable text.", + "kind": "text", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "text_match", + "selector": "slide_text", + "expectation": { + "contains": "AcidSlide Synthesis" + } + }, + "assertion_id": "slide-20.assert-key-text", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-20.native-table -scope: slide -slide: 20 -tier: 3 -title: Native table present -description: Final torture slide must contain a native table. -kind: table -severity: critical -source_of_truth: ooxml -verification: - method: object_compare - selector: table - expectation: - exact_count: 1 - required: true -failure_mode: - automatic_fail_if: - - grouped_lines_and_text_used_as_table - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-20.native-primary", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Primary native construct is present", + "description": "The primary structural requirement is one native line chart with three series; raster or shape imitations do not qualify.", + "kind": "chart", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1, + "required": true + } + }, + "assertion_id": "slide-20.assert-native-primary", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-20.image-present -scope: slide -slide: 20 -tier: 3 -title: Image present -description: Final torture slide must contain at least one embedded image. -kind: image-asset -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: picture - expectation: - min_count: 1 - required: true +{ + "schema_version": "1.0", + "id": "slide-20.layout-binding", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Blank with Footer layout binding", + "description": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "kind": "master-layout", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "layout_check", + "selector": "master_ref", + "expectation": { + "required": true + } + }, + "assertion_id": "slide-20.assert-layout-binding", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-20.groups-present -scope: slide -slide: 20 -tier: 3 -title: Grouped objects present -description: Final torture slide must contain group shapes. -kind: grouping -severity: major -source_of_truth: ooxml -verification: - method: object_compare - selector: group - expectation: - min_count: 1 +{ + "schema_version": "1.0", + "id": "slide-20.font-policy", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Bundled font policy", + "description": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "kind": "typography", + "severity": "critical", + "source_of_truth": "ooxml", + "verification": { + "method": "anti_cheat", + "selector": "font_policy" + }, + "failure_mode": { + "automatic_fail_if": [ + "non_bundled_font_used" + ], + "propagation": "zero_slide", + "affected_slides": { + "status": "complete", + "mode": "current_slide", + "slides": [ + 20 + ], + "selector_id": null, + "selector_sha256": null + } + }, + "assertion_id": "slide-20.assert-font-policy", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} --- -schema_version: "1.0" -id: slide-20.font-policy -scope: slide -slide: 20 -tier: 3 -title: Font policy compliance -description: All fonts on slide 20 must be from the bundled set. -kind: structure -severity: critical -source_of_truth: ooxml -verification: - method: anti_cheat - selector: font_policy -failure_mode: - automatic_fail_if: - - non_bundled_font_used - propagation: zero_slide +{ + "schema_version": "1.0", + "id": "slide-20.composition", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Required composition inventory", + "description": "The slide composition must include chart, 3-by-6 table, approved image, multilingual copy, rotation, groups, gradient, bullets, and fields.", + "kind": "structure", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-20.assert-composition", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.full-slide-fidelity", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Full-slide rendered fidelity", + "description": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999 + } + }, + "assertion_id": "slide-20.assert-full-slide-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.focal-fidelity", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Focal region rendered fidelity", + "description": "The full-slide SSIM gate must preserve the appearance of the full final composite; this label identifies the diagnostic focal region.", + "kind": "visual", + "severity": "major", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic_region": "the full final composite" + } + }, + "assertion_id": "slide-20.assert-focal-fidelity", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.hierarchy-z-order", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Hierarchy and z-order semantics", + "description": "Preserve nested group, overlap stack, field, and master footer relationships in native OOXML and in the rendered result.", + "kind": "z-order", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-20.assert-hierarchy-z-order", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.semantic-structure", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Semantic structure matches prompt", + "description": "The editable object graph must express one native line chart with three series while remaining visually equivalent to the reference.", + "kind": "chart", + "severity": "major", + "source_of_truth": "both", + "verification": { + "method": "object_compare", + "selector": "chart", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-20.assert-semantic-structure", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.palette", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Palette fidelity", + "description": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "kind": "visual", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "palette" + } + }, + "assertion_id": "slide-20.assert-palette", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.typography", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Typography fidelity", + "description": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "kind": "typography", + "severity": "minor", + "source_of_truth": "render", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "typography" + } + }, + "assertion_id": "slide-20.assert-typography", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.spacing", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Geometry and spacing fidelity", + "description": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "kind": "spacing-autofit", + "severity": "minor", + "source_of_truth": "both", + "verification": { + "method": "visual_ssim", + "selector": "full_slide", + "expectation": { + "min_ssim": 0.9999, + "diagnostic": "geometry" + } + }, + "assertion_id": "slide-20.assert-spacing", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} +--- +{ + "schema_version": "1.0", + "id": "slide-20.decorative-detail", + "scope": "slide", + "slide": 20, + "tier": 3, + "title": "Decorative and effect details", + "description": "Preserve image crop, 45-degree label, gradient, bullet spacing, and multilingual typography as editable native detail.", + "kind": "gradient-pattern", + "severity": "minor", + "source_of_truth": "ooxml", + "verification": { + "method": "object_compare", + "selector": "table", + "expectation": { + "min_count": 1 + } + }, + "assertion_id": "slide-20.assert-decorative-detail", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete." + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [] + }, + "lifecycle_state": "candidate" +} diff --git a/acidslide-v1/benchmark/deck/exports/slide-01.png b/acidslide-v1/benchmark/deck/exports/slide-01.png new file mode 100644 index 0000000..bce2b74 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-01.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-02.png b/acidslide-v1/benchmark/deck/exports/slide-02.png new file mode 100644 index 0000000..6973145 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-02.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-03.png b/acidslide-v1/benchmark/deck/exports/slide-03.png new file mode 100644 index 0000000..a457eb4 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-03.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-04.png b/acidslide-v1/benchmark/deck/exports/slide-04.png new file mode 100644 index 0000000..a898d70 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-04.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-05.png b/acidslide-v1/benchmark/deck/exports/slide-05.png new file mode 100644 index 0000000..34a83dc Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-05.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-06.png b/acidslide-v1/benchmark/deck/exports/slide-06.png new file mode 100644 index 0000000..1be9027 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-06.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-07.png b/acidslide-v1/benchmark/deck/exports/slide-07.png new file mode 100644 index 0000000..5dab24e Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-07.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-08.png b/acidslide-v1/benchmark/deck/exports/slide-08.png new file mode 100644 index 0000000..ae0d767 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-08.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-09.png b/acidslide-v1/benchmark/deck/exports/slide-09.png new file mode 100644 index 0000000..c1ee448 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-09.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-10.png b/acidslide-v1/benchmark/deck/exports/slide-10.png new file mode 100644 index 0000000..d0ea8a2 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-10.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-11.png b/acidslide-v1/benchmark/deck/exports/slide-11.png new file mode 100644 index 0000000..9900b28 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-11.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-12.png b/acidslide-v1/benchmark/deck/exports/slide-12.png new file mode 100644 index 0000000..eee0a33 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-12.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-13.png b/acidslide-v1/benchmark/deck/exports/slide-13.png new file mode 100644 index 0000000..e5dcfce Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-13.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-14.png b/acidslide-v1/benchmark/deck/exports/slide-14.png new file mode 100644 index 0000000..1f9833f Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-14.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-15.png b/acidslide-v1/benchmark/deck/exports/slide-15.png new file mode 100644 index 0000000..de62807 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-15.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-16.png b/acidslide-v1/benchmark/deck/exports/slide-16.png new file mode 100644 index 0000000..b6ba3e4 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-16.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-17.png b/acidslide-v1/benchmark/deck/exports/slide-17.png new file mode 100644 index 0000000..e1ed78f Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-17.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-18.png b/acidslide-v1/benchmark/deck/exports/slide-18.png new file mode 100644 index 0000000..372356c Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-18.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-19.png b/acidslide-v1/benchmark/deck/exports/slide-19.png new file mode 100644 index 0000000..a476e0c Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-19.png differ diff --git a/acidslide-v1/benchmark/deck/exports/slide-20.png b/acidslide-v1/benchmark/deck/exports/slide-20.png new file mode 100644 index 0000000..94f3eb5 Binary files /dev/null and b/acidslide-v1/benchmark/deck/exports/slide-20.png differ diff --git a/acidslide-v1/benchmark/deck/gold/acidslide-v1-gold.pptx b/acidslide-v1/benchmark/deck/gold/acidslide-v1-gold.pptx new file mode 100644 index 0000000..7d35810 Binary files /dev/null and b/acidslide-v1/benchmark/deck/gold/acidslide-v1-gold.pptx differ diff --git a/acidslide-v1/benchmark/fixtures/expected-deck.json b/acidslide-v1/benchmark/fixtures/expected-deck.json new file mode 100644 index 0000000..3725cac --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-deck.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout2.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s1:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"subTitle","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"subTitle","table_dimensions":null},"node_id":"s1:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":2160000,"width":3600000,"x":5760000,"y":2880000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"25000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.25","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":2880000,"width":2880000,"x":5040000,"y":1440000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"40000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.4","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":3},{"asset_sha256":"sha256:63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007","bbox":{"height":3060000,"width":5400000,"x":6120000,"y":720000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":true,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s1:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":3600000,"width":2160000,"x":6480000,"y":360000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"30000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.3","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s1:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"44","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":3977640,"width":10972800,"x":609480,"y":1604520},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"subTitle","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"subTitle","table_dimensions":null},"node_id":"s1:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":false,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"Benchmark for Slide Generation Fidelity"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s1:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s1:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"1"}],"z_index":9}],"part_name":"/ppt/slides/slide1.xml","relationships":[{"id":"rId1","target":"/ppt/media/image1.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/slideLayouts/slideLayout2.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":1},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s2:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s2:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s2:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Agenda"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3977640,"width":10972800,"x":609480,"y":1604520},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s2:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Opening Remarks"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Welcome and introductions"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Safety briefing"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Technical Deep Dive"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Architecture overview"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Performance benchmarks"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Security audit results"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Breakout Sessions"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Track A: Infrastructure"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Track B: Applications"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Closing & Next Steps"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":1260000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"09:00"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":2988000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":2988000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"11:30"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":4716000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":4716000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"14:00"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s2:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s2:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"2"}],"z_index":11}],"part_name":"/ppt/slides/slide2.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":2},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":648000,"width":5760000,"x":540000,"y":288000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s3:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Performance Metrics"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4320000,"width":10800000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":5,"rows":7}},"node_id":"s3:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Metric"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q1 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q2 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q3 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Target"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Latency (p50)"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"12ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"11ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"9ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"10ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Latency (p99)"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"89ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"72ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"58ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"75ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Throughput"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,200 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,450 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,890 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"2,000 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Error Rate"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.12%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.08%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.04%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.05%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Uptime"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.91%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.95%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.98%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.95%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Cache Hit"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"72%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"78%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"84%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"80%"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":792000,"width":2880000,"x":8640000,"y":5508000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s3:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide3.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":684000,"width":2736000,"x":8712000,"y":5544000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s3:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Throughput target"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"missed by 5.5%"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s3:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s3:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"3"}],"z_index":5}],"part_name":"/ppt/slides/slide3.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":3},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s4:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s4:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s4:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Revenue Growth"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":5040000,"width":7200000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":10,"series_count":2,"value_point_count":10},"chart_type":"barChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"barChart","table_dimensions":null},"node_id":"s4:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":3240000,"x":8280000,"y":1368000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Key Takeaways:"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":1512000,"width":3240000,"x":8280000,"y":1728000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Native Bullet List","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Total revenue up 38.2% YoY"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"APAC fastest-growing region"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"All regions exceeded targets"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":1774800},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":1956600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":2138400},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":648000,"width":1800000,"x":5220000,"y":3312000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"+62.9% YoY"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":648000,"width":1800000,"x":5220000,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"+84.6% YoY"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s4:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s4:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"4"}],"z_index":12}],"part_name":"/ppt/slides/slide4.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":4},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s5:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s5:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s5:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Our Team"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":540000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":540000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1440000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":1440000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":720000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Sarah Chen"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":720000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Chief Architect"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":864000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"15 years building distributed systems at scale"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Sarah Chen Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Sarah Chen"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Chief Architect"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"15 years building distributed systems at scale"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":4320000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n4.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":5220000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n4.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":5220000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":4500000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Marcus Rivera"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":4500000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Head of Design"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":4644000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Formerly at Apple, obsessed with pixel-perfect interfaces"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Marcus Rivera Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Marcus Rivera"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Head of Design"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Formerly at Apple, obsessed with pixel-perfect interfaces"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":8100000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":8100000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n5.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":9000000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n5.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":9000000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":8280000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Yuki Tanaka"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":8280000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"ML Engineering Lead"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":8424000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PhD in NLP, built the model serving infrastructure"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Yuki Tanaka Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Yuki Tanaka"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"ML Engineering Lead"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PhD in NLP, built the model serving infrastructure"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s5:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s5:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"5"}],"z_index":7}],"part_name":"/ppt/slides/slide5.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":5},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":432000,"width":3420000,"x":432000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"Global Perspectives"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":3060000,"width":3240000,"x":432000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"The rapid advancement of language models"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"has transformed how organizations approach"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"document generation. From financial reports"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"to marketing materials, AI-driven content"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"creation is reshaping every industry."}],"z_index":1},{"asset_sha256":null,"bbox":{"height":735120,"width":3420000,"x":4320000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Noto Sans Arabic","font_size_pt":"24","italic":null,"language":"hi-IN","rtl":true,"text":"وجهات نظر عالمية"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3102840,"width":3240000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"لقد أدى التقدم السريع في نماذج اللغة إلى تحويل"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"كيفية تعامل المؤسسات مع إنشاء المستندات. من"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"التقارير المالية إلى المواد التسويقية، يعيد إنشاء"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة."}],"z_index":3},{"asset_sha256":null,"bbox":{"height":532440,"width":3420000,"x":8280000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Noto Sans CJK JP","font_size_pt":"24","italic":null,"language":"zh-CN","rtl":false,"text":"グローバルな視点"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":3060000,"width":3420000,"x":8280000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"言語モデルの急速な進歩により、組織がドキュメント生成に"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"取り組む方法が変革されました。財務報告からマーケティング"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"資料まで、"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"AI"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"主導のコンテンツ作成はあらゆる産業を"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"再形成しています。"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":4680000,"width":0,"x":4032000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s6:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":4680000,"width":0,"x":8100000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s6:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":1440000,"width":4320000,"x":5400000,"y":4680000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"90000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.9","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s6:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":1152000,"width":4032000,"x":5544000,"y":4824000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"AI-generated slides must handle RTL text,"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"CJK line breaking, and mixed scripts correctly."}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s6:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s6:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"6"}],"z_index":11}],"part_name":"/ppt/slides/slide6.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":6},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s7:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Image Handling"}],"z_index":0},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2880000,"width":3600000,"x":540000,"y":900000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":2362,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":1},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2880000,"width":2880000,"x":4680000,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s7:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":2},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":2880000,"width":3600000,"x":8100000,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s7:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":3600000,"x":540000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Full panorama crop"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":4680000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Circle-masked detail"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":324000,"width":3600000,"x":8100000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rounded corner crop"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":2160000,"width":2160000,"x":5040000,"y":1260000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":"50000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.5","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":504000,"width":1944000,"x":5148000,"y":2016000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"PREVIEW"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s7:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s7:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"7"}],"z_index":10}],"part_name":"/ppt/slides/slide7.xml","relationships":[{"id":"rId1","target":"/ppt/media/image2.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/media/image3.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/media/image4.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId4","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":7},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1080000,"width":12192120,"x":0,"y":5400000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"gradFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s8:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s8:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Depth & Layering"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":3240000,"width":5400000,"x":1440000,"y":1800000},"children":[{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":1440000,"y":2160000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":2520000,"y":1800000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 2"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3600000,"width":6480000,"x":3600000,"y":720000},"children":[{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":3600000,"y":1440000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 3"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"55000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.55","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 4"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":5760000,"y":720000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"90000","color":{"kind":"srgbClr","value":"ffffff"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.9","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 5"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 3"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 4"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 5"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s8:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s8:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"8"}],"z_index":5}],"part_name":"/ppt/slides/slide8.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":8},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s9:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide9.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s9:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide9.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s9:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"API Reference"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":252000,"width":5040000,"x":648000,"y":1008000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Fixed Size (clips)"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":252000,"width":5040000,"x":6480000,"y":1008000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Auto-Shrink (fits)"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":5040000,"width":5040000,"x":648000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"GET /api/v1/submissions"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Authorization: Bearer YOUR_TOKEN_HERE"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Content-Type: application/json"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Query Parameters:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"model_id string required Filter by model"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"tier integer optional 1, 2, or 3"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"status string optional queued|grading|completed"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"limit integer optional Default: 20, max: 100"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"offset integer optional Default: 0"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Response 200:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"submissions\": ["},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"id\": \"sub_abc123\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"model_id\": \"gpt-4o\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"tier\": 3,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"status\": \"completed\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"fidelity_score\": 0.847,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"created_at\": \"2025-01-15T10:30:00Z\""},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"],"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"total\": 142,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"has_more\": true"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"NOTE TO DESIGNER: The parentheses above represent"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces in the actual slide text. When"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"typing this content into the slide, use standard"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces, i.e., the opening and closing"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"brace characters. They are written as parentheses"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"here only because this brief avoids those characters."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":5040000,"width":5040000,"x":6480000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"GET /api/v1/submissions"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Authorization: Bearer YOUR_TOKEN_HERE"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Content-Type: application/json"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Query Parameters:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"model_id string required Filter by model"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"tier integer optional 1, 2, or 3"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"status string optional queued|grading|completed"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"limit integer optional Default: 20, max: 100"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"offset integer optional Default: 0"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Response 200:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"submissions\": ["},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"id\": \"sub_abc123\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"model_id\": \"gpt-4o\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"tier\": 3,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"status\": \"completed\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"fidelity_score\": 0.847,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"created_at\": \"2025-01-15T10:30:00Z\""},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"],"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"total\": 142,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"has_more\": true"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"NOTE TO DESIGNER: The parentheses above represent"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces in the actual slide text. When"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"typing this content into the slide, use standard"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces, i.e., the opening and closing"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"brace characters. They are written as parentheses"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"here only because this brief avoids those characters."},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Error Responses:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"401 Unauthorized - Invalid or expired token"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"403 Forbidden - Rate limit exceeded"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"404 Not Found - Submission not found"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"422 Unprocessable - Invalid parameters"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"500 Internal Server Error - Contact support"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Rate Limits:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Free tier: 10 req/min, 100 req/hour"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Pro tier: 60 req/min, 1000 req/hour"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Enterprise: Custom"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s9:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s9:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"9"}],"z_index":8}],"part_name":"/ppt/slides/slide9.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":9},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s10:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"System Architecture"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":720000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Client App"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"API Gateway"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3060000,"width":7560000,"x":2160000,"y":3240000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":4680000,"x":3600000,"y":3240000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":3600000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":6480000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":7560000,"x":2160000,"y":5220000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":2160000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":7920000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":360,"width":2520360,"x":2520000,"y":1620000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":1080360,"width":1440360,"x":4500000,"y":2160000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"bentConnector3","table_dimensions":null},"node_id":"s10:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":1080360,"width":360,"x":5940000,"y":2160000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":360,"width":360360,"x":6480000,"y":3780000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[4]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":1440360,"width":540360,"x":6840000,"y":4320000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[5]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":360,"width":1080360,"x":3960000,"y":5760000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[6]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":360,"width":1080360,"x":6840000,"y":5760000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[7]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":252000,"width":792000,"x":3060000,"y":1296000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"HTTPS"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":252000,"width":900000,"x":3780000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"JWT verify"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":252000,"width":792000,"x":5400000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Enqueue"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":252000,"width":3960000,"x":3960000,"y":2808000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Processing Layer"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":252000,"width":4680000,"x":3600000,"y":4824000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Persistence Layer"}],"z_index":15},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s10:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s10:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"10"}],"z_index":17}],"part_name":"/ppt/slides/slide10.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":10},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s11:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s11:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s11:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Brand Colors"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1080000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":1080000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Primary"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":4320000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Secondary"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":7560000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":7560000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Accent 1"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1080000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"ff6b35"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":1080000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":4320000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"7b2d8e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":4320000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":7560000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"3d9970"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":13},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":7560000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[15]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":648000,"width":10440000,"x":720000,"y":5508000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[16]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Top row uses theme color references. Bottom row uses explicit RGB values."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Changing the theme will update the top row but not the bottom row."}],"z_index":15},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s11:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[17]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s11:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[18]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"11"}],"z_index":17}],"part_name":"/ppt/slides/slide11.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":11},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s12:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide12.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s12:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide12.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s12:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Document Fields"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":1368000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Current slide: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":""}],"z_index":3},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":1368000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Live slide number field (not static text)"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":2592000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"datetime","field_types":["datetime"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Generated: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"1/3/-1"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":2592000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Fixed date/time field"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":3816000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":3816000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Footer from master placeholder"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Slide 12"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Static text comparison"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s12:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s12:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"12"}],"z_index":12}],"part_name":"/ppt/slides/slide12.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":12},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s13:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Composite Stress"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":3600000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":6,"series_count":1,"value_point_count":6},"chart_type":"pieChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"pieChart","table_dimensions":null},"node_id":"s13:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":2520000,"width":3240000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":3,"rows":4}},"node_id":"s13:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[2]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Check"},{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Status"},{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Weight"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Schema"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"3"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rendering"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"2"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Assets"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Review"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"1"}],"z_index":2},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2160000,"width":2880000,"x":8280000,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":0,"l":2362,"r":0,"t":0},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":466920,"width":6840000,"x":4500000,"y":3960000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"الهيكل والمحتوى والعرض في اختبار واحد"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":648000,"width":2520000,"x":900000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":432000,"width":2376000,"x":972000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE CHART"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":648000,"width":2520000,"x":4680000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":432000,"width":2376000,"x":4752000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE TABLE"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":648000,"width":2700000,"x":8460000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":432000,"width":2556000,"x":8532000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"APPROVED ASSET"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":0,"x":2160000,"y":3960000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":900000,"width":0,"x":5940000,"y":3600000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":12},{"asset_sha256":null,"bbox":{"height":1260000,"width":0,"x":9720000,"y":3240000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":13},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s13:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s13:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"13"}],"z_index":15}],"part_name":"/ppt/slides/slide13.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart2.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/media/image5.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":13},{"layout_part":"/ppt/slideLayouts/slideLayout4.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s14:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":4426920,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s14:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":3288240,"width":4426920,"x":5152680,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s14:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s14:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"RTL Systems Review"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":4500000,"width":0,"x":6084000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s14:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":4320000,"width":5040000,"x":540000,"y":1152000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s14:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"مراجعة الأنظمة الموزعة"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"دقة العرض هي أساس المقارنة بين الأنظمة."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"سلامة البنية تحافظ على المعنى والتفاعل."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"The"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" الذكاء الاصطناعي "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"revolution"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" تتطلب نصاً ثنائي الاتجاه."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"الإصدار "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"AcidSlide v1"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" يختبر التوافق."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"يجب الحفاظ على علامات الترقيم وترتيب "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"Unicode"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":4320000,"width":4860000,"x":6660000,"y":1152000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s14:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"A structural benchmark must preserve meaning and direction."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Rendering alone cannot prove native editability."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Bidirectional runs must retain their Unicode order."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Mirrored padding makes the comparison deliberate."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"The benchmark records both artifact and visual fidelity."}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s14:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s14:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"14"}],"z_index":8}],"part_name":"/ppt/slides/slide14.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout4.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":14},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s15:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Rotation Atlas"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":0,"width":10980000,"x":540000,"y":2880000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"line","table_dimensions":null},"node_id":"s15:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":360000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":540000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Baseline 0°"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":2520000,"y":2519640},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n4","rotation_degrees":"315","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":2700000,"y":2609640},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n5","rotation_degrees":"315","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Diagonal 45°"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":4680000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n6","rotation_degrees":"27","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":4860000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n7","rotation_degrees":"27","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Vertical 90°"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":6839640,"y":2519640},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n8","rotation_degrees":"225","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":7019640,"y":2609640},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n9","rotation_degrees":"225","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Reverse 135°"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":9000000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n10","rotation_degrees":"9","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":9180000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n11","rotation_degrees":"9","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Vertical 270°"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s15:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s15:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"15"}],"z_index":13}],"part_name":"/ppt/slides/slide15.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":15},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":3600000,"width":3600000,"x":-1080000,"y":-720000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Negative Circle","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s16:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":2160000,"width":4320000,"x":10392120,"y":2160000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Right Bleed","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":5760000,"x":2880000,"y":-360000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Top Bleed","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s16:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Beyond the Frame"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":648000,"width":5400000,"x":3240000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"3","italic":null,"language":"en-US","rtl":false,"text":"INTENTIONAL BLEED"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":504000,"width":6480000,"x":2700000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Negative coordinates are part of the composition."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s16:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s16:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"16"}],"z_index":7}],"part_name":"/ppt/slides/slide16.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":16},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s17:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Nested Systems"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4680000,"width":9720000,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":1893240,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":1080000,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.0.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":1312200,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"A1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.0.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"A1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":1080000,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":1893240,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":1080000,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.0.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":1312200,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"A2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.0.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"A2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"INPUT Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":4758840,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":4758840,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":5572080,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":4758840,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.1.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897200,"x":4991400,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"B1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.1.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"B1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":4758840,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":5572080,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":4758840,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.1.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897200,"x":4991400,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"B2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.1.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"B2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PROCESS Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":8437680,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":8437680,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":9250920,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":8437680,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.2.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":8670240,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"C1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.2.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"C1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":8437680,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":9250920,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":8437680,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.2.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":8670240,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"C2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.2.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"C2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"OUTPUT Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Nested Systems Outer Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s17:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s17:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"17"}],"z_index":3}],"part_name":"/ppt/slides/slide17.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":17},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s18:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Three Cities / "},{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"zh-CN","rtl":false,"text":"三つの都市"}],"z_index":0},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":5220000,"width":3420000,"x":4386240,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"Center Column Tiled Pattern","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":1},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":1260000,"width":3420000,"x":642240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":3543,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":642240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Systems"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":642240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Cities expose the systems beneath daily life: transport, energy, data, and the people who connect them."}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":642240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Structure makes the invisible legible.”"}],"z_index":5},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":1260000,"width":3420000,"x":4386240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":12283,"l":0,"r":0,"t":12283},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[2]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":4386240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"zh-CN","rtl":false,"text":"システム"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":4386240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"生成されたスライドは構造と意味を保持します。"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"編集可能な構造が共有された理解を支えます。"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":4386240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"構造は意味を運びます。”"}],"z_index":9},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":1260000,"width":3420000,"x":8130240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":3543,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[3]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":8130240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Shared Futures"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":8130240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"A common visual language lets teams compare evidence, preserve intent, and build toward shared futures."}],"z_index":12},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":8130240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Consistency is a form of trust.”"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s18:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s18:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"18"}],"z_index":15}],"part_name":"/ppt/slides/slide18.xml","relationships":[{"id":"rId1","target":"/ppt/media/image6.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/media/image7.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/media/image8.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId4","target":"/ppt/media/image9.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId5","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":18},{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s19:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s19:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s19:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Design System Audit"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Typography"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":547920,"width":3240000,"x":3060000,"y":972000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Carlito 36"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":396000,"width":3600000,"x":7380000,"y":1044000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Liberation Sans 18"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":2052000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Palette"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":3060000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":5220000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":7380000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":3024000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Spacing"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":3060000,"y":2952000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":4680000,"y":2952000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":12},{"asset_sha256":null,"bbox":{"height":432000,"width":2880000,"x":6480000,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"0.5cm token"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":3996000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[15]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Line Weight"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":6120000,"x":3060000,"y":4140000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"line","table_dimensions":null},"node_id":"s19:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[16]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":15},{"asset_sha256":null,"bbox":{"height":396000,"width":1800000,"x":9540000,"y":3942000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[17]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"0.5pt teal rule"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":4968000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[18]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Navigation"}],"z_index":17},{"asset_sha256":null,"bbox":{"height":468000,"width":3240000,"x":3060000,"y":4860000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":["/ppt/slides/slide1.xml"],"name":"Return to Cover Internal Link","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n18","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[19]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Return to Cover"}],"z_index":18},{"asset_sha256":null,"bbox":{"height":468000,"width":3240000,"x":7380000,"y":4860000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":["/ppt/slides/slide5.xml"],"name":"Meet the Team Internal Link","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n19","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[20]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Meet the Team"}],"z_index":19},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s19:n20","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[21]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":20},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s19:n21","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[22]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"19"}],"z_index":21}],"part_name":"/ppt/slides/slide19.xml","relationships":[{"id":"rId1","target":"/ppt/slides/slide1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"},{"id":"rId2","target":"/ppt/slides/slide5.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":19},{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s20:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide Synthesis"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1980000,"width":3780000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":9,"series_count":3,"value_point_count":9},"chart_type":"lineChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Native Line Chart","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"lineChart","table_dimensions":null},"node_id":"s20:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1620000,"width":6840000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Native Table","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":6,"rows":3}},"node_id":"s20:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Tier"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Slides"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Checks"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"SSIM"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Schema"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Status"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"L1"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"5"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"70"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"0.9999"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Ready"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"L3"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"20"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"280"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"0.9999"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Ready"}],"z_index":2},{"asset_sha256":"sha256:63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007","bbox":{"height":1512000,"width":2340000,"x":4680000,"y":2880000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":0,"l":3937,"r":0,"t":0},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Approved Hero","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":518760,"width":1800000,"x":7380000,"y":2844000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Noto Sans Arabic","font_size_pt":"16","italic":null,"language":"hi-IN","rtl":true,"text":"اختبار شامل"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":396000,"width":1800000,"x":7380000,"y":3312000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Noto Sans CJK JP","font_size_pt":"16","italic":null,"language":"zh-CN","rtl":false,"text":"総合テスト"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":468000,"width":1800000,"x":576000,"y":3636000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Rotated Text","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n6","rotation_degrees":"45","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"ROTATED"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":1296000,"width":2340000,"x":2160000,"y":3528000},"children":[{"asset_sha256":null,"bbox":{"height":1116000,"width":2340000,"x":2160000,"y":3528000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1080000,"x":2160000,"y":3528000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":936000,"width":1260000,"x":2736000,"y":3708000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s20:n7.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1080000,"x":3420000,"y":3528000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Overlap Inner Group","opacity":"1","paragraph_properties":[],"parent_group_path":["s20:n7"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":288000,"width":1872000,"x":2484000,"y":4536000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s20:n7"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n7.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"2-LEVEL GROUP"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Overlap Outer Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"2-LEVEL GROUP"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":792000,"width":2520000,"x":9000000,"y":4032000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"gradFill"},"hyperlink_targets":[],"name":"Synthesis Navy Teal Gradient","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s20:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":504000,"width":2304000,"x":9108000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE GRADIENT"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":900000,"width":4500000,"x":540000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Native Bullet List","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Native structure retained"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Multilingual meaning preserved"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rendered fidelity verified"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":8100000,"y":5148000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Live Slide Number Field","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Live slide: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":""}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s20:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s20:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"20"}],"z_index":13}],"part_name":"/ppt/slides/slide20.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/media/image10.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":20}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-01.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-01.json new file mode 100644 index 0000000..9c45c51 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-01.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout2.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s1:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"subTitle","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"subTitle","table_dimensions":null},"node_id":"s1:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":2160000,"width":3600000,"x":5760000,"y":2880000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"25000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.25","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":2880000,"width":2880000,"x":5040000,"y":1440000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"40000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.4","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":3},{"asset_sha256":"sha256:63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007","bbox":{"height":3060000,"width":5400000,"x":6120000,"y":720000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":true,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s1:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":3600000,"width":2160000,"x":6480000,"y":360000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"30000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.3","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s1:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide1.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s1:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"44","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":3977640,"width":10972800,"x":609480,"y":1604520},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"subTitle","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"subTitle","table_dimensions":null},"node_id":"s1:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":false,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"Benchmark for Slide Generation Fidelity"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s1:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s1:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide1.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"1"}],"z_index":9}],"part_name":"/ppt/slides/slide1.xml","relationships":[{"id":"rId1","target":"/ppt/media/image1.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/slideLayouts/slideLayout2.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":1}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-02.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-02.json new file mode 100644 index 0000000..093e4d8 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-02.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s2:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s2:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s2:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Agenda"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3977640,"width":10972800,"x":609480,"y":1604520},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s2:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Opening Remarks"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Welcome and introductions"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Safety briefing"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Technical Deep Dive"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Architecture overview"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Performance benchmarks"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Security audit results"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Breakout Sessions"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Track A: Infrastructure"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Track B: Applications"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Closing & Next Steps"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":1260000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"09:00"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":2988000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":2988000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"11:30"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":360000,"width":360000,"x":9936000,"y":4716000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s2:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide2.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":360000,"width":1080000,"x":10440000,"y":4716000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s2:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"14:00"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s2:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s2:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide2.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"2"}],"z_index":11}],"part_name":"/ppt/slides/slide2.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":2}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-03.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-03.json new file mode 100644 index 0000000..00169d0 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-03.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":648000,"width":5760000,"x":540000,"y":288000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s3:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Performance Metrics"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4320000,"width":10800000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":5,"rows":7}},"node_id":"s3:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Metric"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q1 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q2 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Q3 2024"},{"bold":true,"font_family":"Carlito","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Target"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Latency (p50)"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"12ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"11ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"9ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"10ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Latency (p99)"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"89ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"72ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"58ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"75ms"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Throughput"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,200 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,450 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"1,890 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"2,000 rps"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Error Rate"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.12%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.08%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.04%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≤"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"0.05%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Uptime"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.91%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.95%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.98%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"99.95%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Cache Hit"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"72%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"78%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"84%"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"≥"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"80%"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":792000,"width":2880000,"x":8640000,"y":5508000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s3:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide3.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":684000,"width":2736000,"x":8712000,"y":5544000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s3:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Throughput target"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"missed by 5.5%"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s3:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s3:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide3.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"3"}],"z_index":5}],"part_name":"/ppt/slides/slide3.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":3}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-04.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-04.json new file mode 100644 index 0000000..ab2e556 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-04.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s4:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s4:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s4:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Revenue Growth"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":5040000,"width":7200000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":10,"series_count":2,"value_point_count":10},"chart_type":"barChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"barChart","table_dimensions":null},"node_id":"s4:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide4.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":3240000,"x":8280000,"y":1368000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Key Takeaways:"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":1512000,"width":3240000,"x":8280000,"y":1728000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Native Bullet List","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"▸"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Total revenue up 38.2% YoY"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"APAC fastest-growing region"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"All regions exceeded targets"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":1774800},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":1956600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":216000,"width":252000,"x":8402400,"y":2138400},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"8","italic":null,"language":"en-US","rtl":false,"text":"►"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":648000,"width":1800000,"x":5220000,"y":3312000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"+62.9% YoY"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":648000,"width":1800000,"x":5220000,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s4:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"+84.6% YoY"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s4:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s4:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide4.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"4"}],"z_index":12}],"part_name":"/ppt/slides/slide4.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":4}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-05.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-05.json new file mode 100644 index 0000000..a513094 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-05.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s5:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s5:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s5:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Our Team"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":540000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":540000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1440000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":1440000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":720000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Sarah Chen"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":720000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Chief Architect"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":864000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n3.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"15 years building distributed systems at scale"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Sarah Chen Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Sarah Chen"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Chief Architect"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"15 years building distributed systems at scale"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":4320000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n4.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":5220000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n4.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":5220000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":4500000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Marcus Rivera"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":4500000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Head of Design"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":4644000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n4"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n4.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Formerly at Apple, obsessed with pixel-perfect interfaces"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Marcus Rivera Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Marcus Rivera"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Head of Design"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Formerly at Apple, obsessed with pixel-perfect interfaces"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":8100000,"y":1188000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":3240000,"x":8100000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"161f2e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n5.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[1]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":9000000,"y":1512000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s5:n5.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[2]","source_part":"/ppt/slides/slide5.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":9000000,"y":1872000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":360000,"width":2880000,"x":8280000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Yuki Tanaka"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":8280000,"y":3672000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"ML Engineering Lead"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":2592000,"x":8424000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s5:n5"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s5:n5.5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]/p:sp[6]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PhD in NLP, built the model serving infrastructure"}],"z_index":5}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Yuki Tanaka Team Card","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s5:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[3]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Photo"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Yuki Tanaka"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"ML Engineering Lead"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PhD in NLP, built the model serving infrastructure"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s5:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s5:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide5.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"5"}],"z_index":7}],"part_name":"/ppt/slides/slide5.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":5}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-06.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-06.json new file mode 100644 index 0000000..1c38db4 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-06.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":432000,"width":3420000,"x":432000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"Global Perspectives"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":3060000,"width":3240000,"x":432000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"The rapid advancement of language models"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"has transformed how organizations approach"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"document generation. From financial reports"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"to marketing materials, AI-driven content"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"creation is reshaping every industry."}],"z_index":1},{"asset_sha256":null,"bbox":{"height":735120,"width":3420000,"x":4320000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Noto Sans Arabic","font_size_pt":"24","italic":null,"language":"hi-IN","rtl":true,"text":"وجهات نظر عالمية"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3102840,"width":3240000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"لقد أدى التقدم السريع في نماذج اللغة إلى تحويل"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"كيفية تعامل المؤسسات مع إنشاء المستندات. من"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"التقارير المالية إلى المواد التسويقية، يعيد إنشاء"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة."}],"z_index":3},{"asset_sha256":null,"bbox":{"height":532440,"width":3420000,"x":8280000,"y":648000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Noto Sans CJK JP","font_size_pt":"24","italic":null,"language":"zh-CN","rtl":false,"text":"グローバルな視点"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":3060000,"width":3420000,"x":8280000,"y":1188000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"言語モデルの急速な進歩により、組織がドキュメント生成に"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"取り組む方法が変革されました。財務報告からマーケティング"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"資料まで、"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"AI"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"主導のコンテンツ作成はあらゆる産業を"},{"bold":false,"font_family":"Noto Sans CJK JP","font_size_pt":"14","italic":null,"language":"zh-CN","rtl":false,"text":"再形成しています。"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":4680000,"width":0,"x":4032000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s6:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":4680000,"width":0,"x":8100000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s6:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":1440000,"width":4320000,"x":5400000,"y":4680000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"90000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.9","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s6:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide6.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":1152000,"width":4032000,"x":5544000,"y":4824000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s6:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"AI-generated slides must handle RTL text,"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"CJK line breaking, and mixed scripts correctly."}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s6:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s6:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide6.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"6"}],"z_index":11}],"part_name":"/ppt/slides/slide6.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":6}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-07.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-07.json new file mode 100644 index 0000000..316d5c1 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-07.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s7:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Image Handling"}],"z_index":0},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2880000,"width":3600000,"x":540000,"y":900000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":2362,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":1},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2880000,"width":2880000,"x":4680000,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s7:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":2},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":2880000,"width":3600000,"x":8100000,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s7:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":324000,"width":3600000,"x":540000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Full panorama crop"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":324000,"width":2880000,"x":4680000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Circle-masked detail"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":324000,"width":3600000,"x":8100000,"y":3888000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rounded corner crop"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":2160000,"width":2160000,"x":5040000,"y":1260000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":"50000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.5","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide7.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":504000,"width":1944000,"x":5148000,"y":2016000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s7:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"24","italic":null,"language":"en-US","rtl":false,"text":"PREVIEW"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s7:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s7:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide7.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"7"}],"z_index":10}],"part_name":"/ppt/slides/slide7.xml","relationships":[{"id":"rId1","target":"/ppt/media/image2.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/media/image3.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/media/image4.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId4","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":7}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-08.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-08.json new file mode 100644 index 0000000..25e8c74 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-08.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1080000,"width":12192120,"x":0,"y":5400000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"gradFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s8:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s8:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Depth & Layering"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":3240000,"width":5400000,"x":1440000,"y":1800000},"children":[{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":1440000,"y":2160000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":2520000,"y":1800000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 2"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3600000,"width":6480000,"x":3600000,"y":720000},"children":[{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":3600000,"y":1440000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 3"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"55000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.55","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 4"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":2880000,"width":4320000,"x":5760000,"y":720000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"90000","color":{"kind":"srgbClr","value":"ffffff"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.9","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s8:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 5"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s8:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[2]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 3"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 4"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Layer 5"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s8:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s8:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide8.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"8"}],"z_index":5}],"part_name":"/ppt/slides/slide8.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":8}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-09.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-09.json new file mode 100644 index 0000000..e1c89cc --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-09.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s9:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide9.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s9:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide9.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s9:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"API Reference"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":252000,"width":5040000,"x":648000,"y":1008000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Fixed Size (clips)"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":252000,"width":5040000,"x":6480000,"y":1008000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Auto-Shrink (fits)"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":5040000,"width":5040000,"x":648000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"GET /api/v1/submissions"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Authorization: Bearer YOUR_TOKEN_HERE"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Content-Type: application/json"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Query Parameters:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"model_id string required Filter by model"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"tier integer optional 1, 2, or 3"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"status string optional queued|grading|completed"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"limit integer optional Default: 20, max: 100"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"offset integer optional Default: 0"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Response 200:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"submissions\": ["},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"id\": \"sub_abc123\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"model_id\": \"gpt-4o\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"tier\": 3,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"status\": \"completed\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"fidelity_score\": 0.847,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"created_at\": \"2025-01-15T10:30:00Z\""},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"],"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"total\": 142,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"has_more\": true"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"NOTE TO DESIGNER: The parentheses above represent"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces in the actual slide text. When"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"typing this content into the slide, use standard"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces, i.e., the opening and closing"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"brace characters. They are written as parentheses"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"here only because this brief avoids those characters."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":5040000,"width":5040000,"x":6480000,"y":1260000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":{"kind":"spcPct","value":115000},"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s9:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"GET /api/v1/submissions"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Authorization: Bearer YOUR_TOKEN_HERE"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Content-Type: application/json"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Query Parameters:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"model_id string required Filter by model"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"tier integer optional 1, 2, or 3"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"status string optional queued|grading|completed"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"limit integer optional Default: 20, max: 100"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"offset integer optional Default: 0"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Response 200:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"submissions\": ["},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"{"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"id\": \"sub_abc123\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"model_id\": \"gpt-4o\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"tier\": 3,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"status\": \"completed\","},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"fidelity_score\": 0.847,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"created_at\": \"2025-01-15T10:30:00Z\""},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"],"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"total\": 142,"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"\"has_more\": true"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"}"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"NOTE TO DESIGNER: The parentheses above represent"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces in the actual slide text. When"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"typing this content into the slide, use standard"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"JSON curly braces, i.e., the opening and closing"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"brace characters. They are written as parentheses"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"here only because this brief avoids those characters."},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Error Responses:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"401 Unauthorized - Invalid or expired token"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"403 Forbidden - Rate limit exceeded"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"404 Not Found - Submission not found"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"422 Unprocessable - Invalid parameters"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"500 Internal Server Error - Contact support"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Rate Limits:"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Free tier: 10 req/min, 100 req/hour"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Pro tier: 60 req/min, 1000 req/hour"},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":" "},{"bold":false,"font_family":"Liberation Mono","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Enterprise: Custom"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s9:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s9:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide9.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"9"}],"z_index":8}],"part_name":"/ppt/slides/slide9.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":9}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-10.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-10.json new file mode 100644 index 0000000..f29a52f --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-10.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s10:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"System Architecture"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":720000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Client App"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"API Gateway"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":3060000,"width":7560000,"x":2160000,"y":3240000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":4680000,"x":3600000,"y":3240000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":3600000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":6480000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":7560000,"x":2160000,"y":5220000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":2160000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":5040000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1800000,"x":7920000,"y":5220000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3","s10:n3.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s10:n3"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"roundRect","table_dimensions":null},"node_id":"s10:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Auth Service"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Job Queue"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Grader"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"PostgreSQL"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Object Store"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Leaderboard"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":360,"width":2520360,"x":2520000,"y":1620000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[1]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":1080360,"width":1440360,"x":4500000,"y":2160000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"bentConnector3","table_dimensions":null},"node_id":"s10:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[2]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":1080360,"width":360,"x":5940000,"y":2160000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[3]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":360,"width":360360,"x":6480000,"y":3780000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[4]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":1440360,"width":540360,"x":6840000,"y":4320000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[5]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":360,"width":1080360,"x":3960000,"y":5760000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[6]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":360,"width":1080360,"x":6840000,"y":5760000},"children":[],"hidden":false,"kind":"connector","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"cxnSp","stroke":{"dash":null,"present":true,"width_emu":19080},"subtype":"straightConnector1","table_dimensions":null},"node_id":"s10:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:cxnSp[7]","source_part":"/ppt/slides/slide10.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":252000,"width":792000,"x":3060000,"y":1296000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"HTTPS"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":252000,"width":900000,"x":3780000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"JWT verify"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":252000,"width":792000,"x":5400000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Enqueue"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":252000,"width":3960000,"x":3960000,"y":2808000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Processing Layer"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":252000,"width":4680000,"x":3600000,"y":4824000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s10:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Persistence Layer"}],"z_index":15},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s10:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s10:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide10.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"10"}],"z_index":17}],"part_name":"/ppt/slides/slide10.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":10}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-11.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-11.json new file mode 100644 index 0000000..40172eb --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-11.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s11:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s11:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s11:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Brand Colors"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1080000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":1080000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Primary"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":4320000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":4320000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Secondary"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":7560000,"y":1188000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":7560000,"y":2700000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Accent 1"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":1080000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"ff6b35"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":1080000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":4320000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"7b2d8e"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":4320000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":1440000,"width":1440000,"x":7560000,"y":3420000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"3d9970"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s11:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide11.xml","text_runs":[],"z_index":13},{"asset_sha256":null,"bbox":{"height":288000,"width":1440000,"x":7560000,"y":4932000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[15]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Override"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":648000,"width":10440000,"x":720000,"y":5508000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s11:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[16]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Top row uses theme color references. Bottom row uses explicit RGB values."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Changing the theme will update the top row but not the bottom row."}],"z_index":15},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s11:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[17]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s11:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[18]","source_part":"/ppt/slides/slide11.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"11"}],"z_index":17}],"part_name":"/ppt/slides/slide11.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":11}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-12.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-12.json new file mode 100644 index 0000000..f6d53b2 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-12.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s12:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide12.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s12:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide12.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s12:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Document Fields"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":1368000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Current slide: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":""}],"z_index":3},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":1368000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Live slide number field (not static text)"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":2592000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"datetime","field_types":["datetime"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Generated: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"1/3/-1"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":2592000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Fixed date/time field"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":3816000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":3816000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"← "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Footer from master placeholder"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":900000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Slide 12"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":540000,"width":5040000,"x":6120000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s12:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Static text comparison"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s12:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s12:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide12.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"12"}],"z_index":12}],"part_name":"/ppt/slides/slide12.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":12}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-13.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-13.json new file mode 100644 index 0000000..a935c5c --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-13.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s13:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Composite Stress"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":2880000,"width":3600000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":6,"series_count":1,"value_point_count":6},"chart_type":"pieChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"pieChart","table_dimensions":null},"node_id":"s13:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":2520000,"width":3240000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":3,"rows":4}},"node_id":"s13:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[2]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Check"},{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Status"},{"bold":true,"font_family":"Carlito","font_size_pt":"13","italic":null,"language":"en-US","rtl":false,"text":"Weight"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Schema"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"3"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rendering"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"2"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Assets"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Review"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"1"}],"z_index":2},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":2160000,"width":2880000,"x":8280000,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":0,"l":2362,"r":0,"t":0},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":466920,"width":6840000,"x":4500000,"y":3960000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"الهيكل والمحتوى والعرض في اختبار واحد"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":648000,"width":2520000,"x":900000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":5},{"asset_sha256":null,"bbox":{"height":432000,"width":2376000,"x":972000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE CHART"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":648000,"width":2520000,"x":4680000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":432000,"width":2376000,"x":4752000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE TABLE"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":648000,"width":2700000,"x":8460000,"y":4500000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s13:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":432000,"width":2556000,"x":8532000,"y":4608000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s13:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"APPROVED ASSET"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":0,"x":2160000,"y":3960000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":900000,"width":0,"x":5940000,"y":3600000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":12},{"asset_sha256":null,"bbox":{"height":1260000,"width":0,"x":9720000,"y":3240000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s13:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide13.xml","text_runs":[],"z_index":13},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s13:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s13:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide13.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"13"}],"z_index":15}],"part_name":"/ppt/slides/slide13.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart2.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/media/image5.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":13}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-14.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-14.json new file mode 100644 index 0000000..cce3aa9 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-14.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout4.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s14:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":4426920,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s14:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":3288240,"width":4426920,"x":5152680,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s14:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s14:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"RTL Systems Review"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":4500000,"width":0,"x":6084000,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":12600},"subtype":"line","table_dimensions":null},"node_id":"s14:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide14.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":4320000,"width":5040000,"x":540000,"y":1152000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]},{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s14:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"مراجعة الأنظمة الموزعة"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"دقة العرض هي أساس المقارنة بين الأنظمة."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"سلامة البنية تحافظ على المعنى والتفاعل."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"The"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" الذكاء الاصطناعي "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"revolution"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" تتطلب نصاً ثنائي الاتجاه."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"الإصدار "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"AcidSlide v1"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":" يختبر التوافق."},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"hi-IN","rtl":true,"text":"يجب الحفاظ على علامات الترقيم وترتيب "},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"Unicode"},{"bold":false,"font_family":"Noto Sans Arabic","font_size_pt":"14","italic":null,"language":"en-US","rtl":true,"text":"."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":4320000,"width":4860000,"x":6660000,"y":1152000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s14:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"A structural benchmark must preserve meaning and direction."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Rendering alone cannot prove native editability."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Bidirectional runs must retain their Unicode order."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Mirrored padding makes the comparison deliberate."},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"The benchmark records both artifact and visual fidelity."}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s14:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 6","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s14:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide14.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"14"}],"z_index":8}],"part_name":"/ppt/slides/slide14.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout4.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":14}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-15.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-15.json new file mode 100644 index 0000000..41689c0 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-15.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s15:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Rotation Atlas"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":0,"width":10980000,"x":540000,"y":2880000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"line","table_dimensions":null},"node_id":"s15:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":360000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":540000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Baseline 0°"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":2520000,"y":2519640},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n4","rotation_degrees":"315","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":4},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":2700000,"y":2609640},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n5","rotation_degrees":"315","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Diagonal 45°"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":4680000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n6","rotation_degrees":"27","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":4860000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n7","rotation_degrees":"27","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Vertical 90°"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":6839640,"y":2519640},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n8","rotation_degrees":"225","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":7019640,"y":2609640},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n9","rotation_degrees":"225","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Reverse 135°"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":720000,"width":2160000,"x":9000000,"y":2520000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"70000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.7","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s15:n10","rotation_degrees":"9","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide15.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":1800000,"x":9180000,"y":2610000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s15:n11","rotation_degrees":"9","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Vertical 270°"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s15:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s15:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide15.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"15"}],"z_index":13}],"part_name":"/ppt/slides/slide15.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":15}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-16.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-16.json new file mode 100644 index 0000000..fa19658 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-16.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":3600000,"width":3600000,"x":-1080000,"y":-720000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Negative Circle","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s16:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":2160000,"width":4320000,"x":10392120,"y":2160000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Right Bleed","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":5760000,"x":2880000,"y":-360000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"Intentional Top Bleed","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide16.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s16:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Beyond the Frame"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":648000,"width":5400000,"x":3240000,"y":2340000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"3","italic":null,"language":"en-US","rtl":false,"text":"INTENTIONAL BLEED"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":504000,"width":6480000,"x":2700000,"y":3240000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s16:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"16","italic":null,"language":"en-US","rtl":false,"text":"Negative coordinates are part of the composition."}],"z_index":5},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s16:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s16:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide16.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"16"}],"z_index":7}],"part_name":"/ppt/slides/slide16.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":16}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-17.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-17.json new file mode 100644 index 0000000..638e88b --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-17.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s17:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Nested Systems"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4680000,"width":9720000,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":1080000,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":1893240,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":1080000,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.0.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":1312200,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"A1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.0.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"A1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":1080000,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":1893240,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":1080000,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"A2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.0.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":1312200,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"A2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0","s17:n1.0.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.0.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"A2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"INPUT Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":4758840,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":4758840,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":5572080,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":4758840,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.1.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897200,"x":4991400,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"B1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.1.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"B1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":4758840,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":5572080,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":4758840,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"d4a843"},"kind":"solidFill"},"hyperlink_targets":[],"name":"B2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.1.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897200,"x":4991400,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"B2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1","s17:n1.1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.1.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"B2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PROCESS Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":4680000,"width":2362320,"x":8437680,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":8437680,"y":1080000},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":9250920,"y":1080000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C1 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134360,"width":2362320,"x":8437680,"y":1505520},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C1 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.2.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":8670240,"y":1812600},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"C1 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.2.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"C1 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1559880,"width":2362320,"x":8437680,"y":4200120},"children":[{"asset_sha256":null,"bbox":{"height":898200,"width":735840,"x":9250920,"y":4200120},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"45000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C2 Circle","opacity":"0.45","paragraph_properties":[],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.1.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":1134720,"width":2362320,"x":8437680,"y":4625280},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"85000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"C2 Panel","opacity":"0.85","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s17:n1.2.1.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":472680,"width":1897560,"x":8670240,"y":4932720},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"C2 Label","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2","s17:n1.2.1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s17:n1.2.1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"C2 Inner Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1","s17:n1.2"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]/p:grpSp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"OUTPUT Middle Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s17:n1"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Nested Systems Outer Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s17:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"INPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"A2"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"PROCESS"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"B2"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C1"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"OUTPUT"},{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"C2"}],"z_index":1},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s17:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s17:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide17.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"17"}],"z_index":3}],"part_name":"/ppt/slides/slide17.xml","relationships":[{"id":"rId1","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":17}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-18.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-18.json new file mode 100644 index 0000000..07691d7 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-18.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s18:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Three Cities / "},{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"zh-CN","rtl":false,"text":"三つの都市"}],"z_index":0},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":5220000,"width":3420000,"x":4386240,"y":900000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"blipFill"},"hyperlink_targets":[],"name":"Center Column Tiled Pattern","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":1},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":1260000,"width":3420000,"x":642240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":3543,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":2},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":642240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Systems"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":642240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Cities expose the systems beneath daily life: transport, energy, data, and the people who connect them."}],"z_index":4},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":642240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Structure makes the invisible legible.”"}],"z_index":5},{"asset_sha256":"sha256:4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385","bbox":{"height":1260000,"width":3420000,"x":4386240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":12283,"l":0,"r":0,"t":12283},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[2]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":6},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":4386240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"zh-CN","rtl":false,"text":"システム"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":4386240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"生成されたスライドは構造と意味を保持します。"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"編集可能な構造が共有された理解を支えます。"}],"z_index":8},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":4386240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"zh-CN","rtl":false,"text":"構造は意味を運びます。”"}],"z_index":9},{"asset_sha256":"sha256:9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a","bbox":{"height":1260000,"width":3420000,"x":8130240,"y":1080000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":3543,"l":0,"r":0,"t":3543},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[3]","source_part":"/ppt/slides/slide18.xml","text_runs":[],"z_index":10},{"asset_sha256":null,"bbox":{"height":396000,"width":3420000,"x":8130240,"y":2484000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"2","italic":null,"language":"en-US","rtl":false,"text":"Shared Futures"}],"z_index":11},{"asset_sha256":null,"bbox":{"height":1656000,"width":3420000,"x":8130240,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s18:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"A common visual language lets teams compare evidence, preserve intent, and build toward shared futures."}],"z_index":12},{"asset_sha256":null,"bbox":{"height":900000,"width":3420000,"x":8130240,"y":4752000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"80000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.8","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"roundRect","table_dimensions":null},"node_id":"s18:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"“"},{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Consistency is a form of trust.”"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s18:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s18:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide18.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"18"}],"z_index":15}],"part_name":"/ppt/slides/slide18.xml","relationships":[{"id":"rId1","target":"/ppt/media/image6.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId2","target":"/ppt/media/image7.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/media/image8.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId4","target":"/ppt/media/image9.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId5","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":18}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-19.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-19.json new file mode 100644 index 0000000..43b7ff2 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-19.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout3.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":946440,"width":9071640,"x":504000,"y":226080},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s19:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":3288240,"width":9071640,"x":504000,"y":1326600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"body","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"body","table_dimensions":null},"node_id":"s19:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s19:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Design System Audit"}],"z_index":2},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":1080000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Typography"}],"z_index":3},{"asset_sha256":null,"bbox":{"height":547920,"width":3240000,"x":3060000,"y":972000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"Carlito 36"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":396000,"width":3600000,"x":7380000,"y":1044000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Liberation Sans 18"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":2052000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n6","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Palette"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":3060000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":7},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":5220000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":504000,"width":1800000,"x":7380000,"y":1944000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":9},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":3024000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[11]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Spacing"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":3060000,"y":2952000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[12]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":11},{"asset_sha256":null,"bbox":{"height":432000,"width":1440000,"x":4680000,"y":2952000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[13]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":12},{"asset_sha256":null,"bbox":{"height":432000,"width":2880000,"x":6480000,"y":2952000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[14]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"0.5cm token"}],"z_index":13},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":3996000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n14","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[15]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Line Weight"}],"z_index":14},{"asset_sha256":null,"bbox":{"height":0,"width":6120000,"x":3060000,"y":4140000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":true,"width_emu":6480},"subtype":"line","table_dimensions":null},"node_id":"s19:n15","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[16]","source_part":"/ppt/slides/slide19.xml","text_runs":[],"z_index":15},{"asset_sha256":null,"bbox":{"height":396000,"width":1800000,"x":9540000,"y":3942000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n16","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[17]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"0.5pt teal rule"}],"z_index":16},{"asset_sha256":null,"bbox":{"height":324000,"width":1980000,"x":648000,"y":4968000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n17","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[18]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"14","italic":null,"language":"en-US","rtl":false,"text":"Navigation"}],"z_index":17},{"asset_sha256":null,"bbox":{"height":468000,"width":3240000,"x":3060000,"y":4860000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":["/ppt/slides/slide1.xml"],"name":"Return to Cover Internal Link","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n18","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[19]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Return to Cover"}],"z_index":18},{"asset_sha256":null,"bbox":{"height":468000,"width":3240000,"x":7380000,"y":4860000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":["/ppt/slides/slide5.xml"],"name":"Meet the Team Internal Link","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s19:n19","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[20]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Meet the Team"}],"z_index":19},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 4","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s19:n20","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[21]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":20},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 5","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s19:n21","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[22]","source_part":"/ppt/slides/slide19.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"19"}],"z_index":21}],"part_name":"/ppt/slides/slide19.xml","relationships":[{"id":"rId1","target":"/ppt/slides/slide1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"},{"id":"rId2","target":"/ppt/slides/slide5.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":19}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-20.json b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-20.json new file mode 100644 index 0000000..acfbb00 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/expected-scenegraphs/slide-20.json @@ -0,0 +1 @@ +{"gold_ooxml_is_oracle":false,"mce_resolved_package_sha256":"sha256:23a7b1fb4fa07c3ecf386413d71e2c142eccbbb3165bcc257b573f177f531dc6","profile_sha256":"sha256:e2ad051b5aff48e8566bf26d239acf4309619f9b5325497198a97be0e64211ab","schema_version":"1.0","slide_size":{"height":6858000,"width":12192000},"slides":[{"layout_part":"/ppt/slideLayouts/slideLayout1.xml","master_part":"/ppt/slideMasters/slideMaster1.xml","nodes":[{"asset_sha256":null,"bbox":{"height":1145160,"width":10972800,"x":609480,"y":273600},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"PlaceHolder 1","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":"title","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"title","table_dimensions":null},"node_id":"s20:n0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"36","italic":null,"language":"en-US","rtl":false,"text":"AcidSlide Synthesis"}],"z_index":0},{"asset_sha256":null,"bbox":{"height":1980000,"width":3780000,"x":540000,"y":1080000},"children":[],"hidden":false,"kind":"chart","native_properties":{"chart_data_summary":{"category_point_count":9,"series_count":3,"value_point_count":9},"chart_type":"lineChart","crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Native Line Chart","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"lineChart","table_dimensions":null},"node_id":"s20:n1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1620000,"width":6840000,"x":4680000,"y":1080000},"children":[],"hidden":false,"kind":"table","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Native Table","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]},{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"graphicFrame","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":null,"table_dimensions":{"columns":6,"rows":3}},"node_id":"s20:n2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:graphicFrame[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Tier"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Slides"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Checks"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"SSIM"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Schema"},{"bold":true,"font_family":"Carlito","font_size_pt":"11","italic":null,"language":"en-US","rtl":false,"text":"Status"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"L1"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"5"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"70"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"0.9999"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Ready"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"L3"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"20"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"280"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"0.9999"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Pass"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"Ready"}],"z_index":2},{"asset_sha256":"sha256:63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007","bbox":{"height":1512000,"width":2340000,"x":4680000,"y":2880000},"children":[],"hidden":false,"kind":"picture","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":{"b":0,"l":3937,"r":0,"t":0},"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Approved Hero","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"pic","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n3","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:pic[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":3},{"asset_sha256":null,"bbox":{"height":518760,"width":1800000,"x":7380000,"y":2844000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"r","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":true,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n4","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Noto Sans Arabic","font_size_pt":"16","italic":null,"language":"hi-IN","rtl":true,"text":"اختبار شامل"}],"z_index":4},{"asset_sha256":null,"bbox":{"height":396000,"width":1800000,"x":7380000,"y":3312000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n5","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[3]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Noto Sans CJK JP","font_size_pt":"16","italic":null,"language":"zh-CN","rtl":false,"text":"総合テスト"}],"z_index":5},{"asset_sha256":null,"bbox":{"height":468000,"width":1800000,"x":576000,"y":3636000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Rotated Text","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n6","rotation_degrees":"45","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[4]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Carlito","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"ROTATED"}],"z_index":6},{"asset_sha256":null,"bbox":{"height":1296000,"width":2340000,"x":2160000,"y":3528000},"children":[{"asset_sha256":null,"bbox":{"height":1116000,"width":2340000,"x":2160000,"y":3528000},"children":[{"asset_sha256":null,"bbox":{"height":1080000,"width":1080000,"x":2160000,"y":3528000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"1b2a4a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":936000,"width":1260000,"x":2736000,"y":3708000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"e8634a"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s20:n7.0.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[2]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":1},{"asset_sha256":null,"bbox":{"height":1080000,"width":1080000,"x":3420000,"y":3528000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":"65000","color":{"kind":"srgbClr","value":"2aacb8"},"kind":"solidFill"},"hyperlink_targets":[],"name":"","opacity":"0.65","paragraph_properties":[],"parent_group_path":["s20:n7","s20:n7.0"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0.2","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]/p:sp[3]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":2}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Overlap Inner Group","opacity":"1","paragraph_properties":[],"parent_group_path":["s20:n7"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7.0","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:grpSp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":0},{"asset_sha256":null,"bbox":{"height":288000,"width":1872000,"x":2484000,"y":4536000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":["s20:n7"],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n7.1","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]/p:sp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"2-LEVEL GROUP"}],"z_index":1}],"hidden":false,"kind":"group","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"Synthesis Overlap Outer Group","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"grpSp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ellipse","table_dimensions":null},"node_id":"s20:n7","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:grpSp[1]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"1","italic":null,"language":"en-US","rtl":false,"text":"2-LEVEL GROUP"}],"z_index":7},{"asset_sha256":null,"bbox":{"height":792000,"width":2520000,"x":9000000,"y":4032000},"children":[],"hidden":false,"kind":"shape","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":true,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"gradFill"},"hyperlink_targets":[],"name":"Synthesis Navy Teal Gradient","opacity":"1","paragraph_properties":[],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"roundRect","table_dimensions":null},"node_id":"s20:n8","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[5]","source_part":"/ppt/slides/slide20.xml","text_runs":[],"z_index":8},{"asset_sha256":null,"bbox":{"height":504000,"width":2304000,"x":9108000,"y":4176000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"","opacity":"1","paragraph_properties":[{"alignment":"ctr","bullet":{"kind":"buNone","value":null},"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n9","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[6]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":true,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"NATIVE GRADIENT"}],"z_index":9},{"asset_sha256":null,"bbox":{"height":900000,"width":4500000,"x":540000,"y":5040000},"children":[],"hidden":false,"kind":"text","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Native Bullet List","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]},{"alignment":null,"bullet":{"kind":"buChar","value":"•"},"indent":-144000,"level":null,"line_spacing":null,"margin_left":216000,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n10","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[7]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Native structure retained"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Multilingual meaning preserved"},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"12","italic":null,"language":"en-US","rtl":false,"text":"Rendered fidelity verified"}],"z_index":10},{"asset_sha256":null,"bbox":{"height":540000,"width":5220000,"x":8100000,"y":5148000},"children":[],"hidden":false,"kind":"field","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"noFill"},"hyperlink_targets":[],"name":"Synthesis Live Slide Number Field","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":null,"placeholder_type":null,"shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":0},"subtype":"rect","table_dimensions":null},"node_id":"s20:n11","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[8]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":"Live slide: "},{"bold":false,"font_family":"Liberation Sans","font_size_pt":"18","italic":null,"language":"en-US","rtl":false,"text":""}],"z_index":11},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":null,"field_types":[],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 2","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":1,"placeholder_type":"ftr","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"ftr","table_dimensions":null},"node_id":"s20:n12","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[9]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"AcidSlide Benchmark v1"}],"z_index":12},{"asset_sha256":null,"bbox":{"height":0,"width":0,"x":0,"y":0},"children":[],"hidden":false,"kind":"placeholder","native_properties":{"chart_data_summary":null,"chart_type":null,"crop":null,"crop_to_shape":false,"field_type":"slidenum","field_types":["slidenum"],"fill":{"alpha":null,"color":null,"kind":"inherited"},"hyperlink_targets":[],"name":"PlaceHolder 3","opacity":"1","paragraph_properties":[{"alignment":null,"bullet":null,"indent":null,"level":null,"line_spacing":null,"margin_left":null,"rtl":false,"tab_stops":[]}],"parent_group_path":[],"placeholder_index":2,"placeholder_type":"sldNum","shadow":false,"source_xml_kind":"sp","stroke":{"dash":null,"present":false,"width_emu":null},"subtype":"sldNum","table_dimensions":null},"node_id":"s20:n13","rotation_degrees":"0","source_locator":"/p:sld/p:cSld/p:spTree/p:sp[10]","source_part":"/ppt/slides/slide20.xml","text_runs":[{"bold":null,"font_family":null,"font_size_pt":null,"italic":null,"language":null,"rtl":false,"text":"20"}],"z_index":13}],"part_name":"/ppt/slides/slide20.xml","relationships":[{"id":"rId1","target":"/ppt/charts/chart3.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"},{"id":"rId2","target":"/ppt/media/image10.png","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"},{"id":"rId3","target":"/ppt/slideLayouts/slideLayout1.xml","target_mode":"Internal","type":"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}],"slide":20}],"units":"EMU"} \ No newline at end of file diff --git a/acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json b/acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json new file mode 100644 index 0000000..f49c4f6 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json @@ -0,0 +1,3748 @@ +{ + "evidence_scope": "generated operator behavior only; not independent assertion provenance, review, or evidence", + "execution_report_id": "acidslide-generated-mutation-execution-v1", + "fixture_index_id": "acidslide-generated-mutation-fixture-index-v1", + "results": [ + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.alignment-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.alignment-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "0000000000000000000000000000000000000000000000000000000000000000", + "before": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "changed_path": "media_hashes[ppt/media/cityscape.bin]", + "checklist_item_id": "deck.approved-assets", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.approved-assets", + "mutation_operator": "replace-one-approved-asset-hash", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0, + "before": 1, + "changed_path": "master_names.length", + "checklist_item_id": "deck.cross-slide-hierarchy", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.cross-slide-hierarchy", + "mutation_operator": "decrement-master-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.effect-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.effect-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 2 + ], + "after": "Arial", + "before": "Noto Sans", + "changed_path": "slides[2].objects[0].text_runs[0].font_family", + "checklist_item_id": "deck.font-policy", + "expected_negative_affected_slides": [ + 2 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 3, + "before": 4, + "changed_path": "layout_names.length", + "checklist_item_id": "deck.layouts-defined", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.layouts-defined", + "mutation_operator": "decrement-layout-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.line-weight-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.line-weight-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0, + "before": 1, + "changed_path": "master_names.length", + "checklist_item_id": "deck.master-present", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.master-present", + "mutation_operator": "decrement-master-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.master-visual-consistency", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.master-visual-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 19, + "before": 20, + "changed_path": "slides.length", + "checklist_item_id": "deck.native-object-coverage", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.native-object-coverage", + "mutation_operator": "change-exact-slide-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0, + "before": 1, + "changed_path": "master_names.length", + "checklist_item_id": "deck.native-slide-numbers", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.native-slide-numbers", + "mutation_operator": "decrement-master-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 1 + ], + "after": [ + 1 + ], + "before": [], + "changed_path": "notes_slides", + "checklist_item_id": "deck.no-notes", + "expected_negative_affected_slides": [ + 1 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.no-notes", + "mutation_operator": "add-speaker-notes-relationship", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 19, + "before": 20, + "changed_path": "slides.length", + "checklist_item_id": "deck.ordered-tier-prefix", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.ordered-tier-prefix", + "mutation_operator": "change-exact-slide-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.palette-consistency", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.palette-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.render-consistency", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.render-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 19, + "before": 20, + "changed_path": "slides.length", + "checklist_item_id": "deck.rtl-cjk-coverage", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.rtl-cjk-coverage", + "mutation_operator": "change-exact-slide-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 19, + "before": 20, + "changed_path": "slides.length", + "checklist_item_id": "deck.slide-count", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.slide-count", + "mutation_operator": "change-exact-slide-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.spacing-consistency", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.spacing-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0, + "before": 1, + "changed_path": "master_names.length", + "checklist_item_id": "deck.theme-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.theme-structure", + "mutation_operator": "decrement-master-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "deck.typography-consistency", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.deck.typography-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[1].objects[2]", + "checklist_item_id": "slide-01.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[1].objects[2]", + "checklist_item_id": "slide-01.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[1].ssim", + "checklist_item_id": "slide-01.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 1 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[1].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-01.font-policy", + "expected_negative_affected_slides": [ + 1 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[1].ssim", + "checklist_item_id": "slide-01.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[1].objects[2]", + "checklist_item_id": "slide-01.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "AcidSlide v1", + "changed_path": "slides[1].objects[0].text_runs[0].text", + "checklist_item_id": "slide-01.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[1].objects[0]", + "checklist_item_id": "slide-01.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "0000000000000000000000000000000000000000000000000000000000000000", + "before": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007", + "changed_path": "media_hashes[ppt/media/fixture.bin]", + "checklist_item_id": "slide-01.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[1].ssim", + "checklist_item_id": "slide-01.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[1].objects[0]", + "checklist_item_id": "slide-01.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[1].ssim", + "checklist_item_id": "slide-01.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[1].ssim", + "checklist_item_id": "slide-01.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-01.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[2].objects[6]", + "checklist_item_id": "slide-02.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[2].objects[6]", + "checklist_item_id": "slide-02.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "slide-02.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 2 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[2].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-02.font-policy", + "expected_negative_affected_slides": [ + 2 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "slide-02.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[2].objects[6]", + "checklist_item_id": "slide-02.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Agenda", + "changed_path": "slides[2].objects[0].text_runs[0].text", + "checklist_item_id": "slide-02.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[2].objects[0]", + "checklist_item_id": "slide-02.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[2].objects[0]", + "checklist_item_id": "slide-02.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.native-primary", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "slide-02.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[2].objects[0]", + "checklist_item_id": "slide-02.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "slide-02.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[2].ssim", + "checklist_item_id": "slide-02.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-02.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[3].objects[1]", + "checklist_item_id": "slide-03.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[3].objects[1]", + "checklist_item_id": "slide-03.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[3].ssim", + "checklist_item_id": "slide-03.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 3 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[3].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-03.font-policy", + "expected_negative_affected_slides": [ + 3 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[3].ssim", + "checklist_item_id": "slide-03.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[3].objects[1]", + "checklist_item_id": "slide-03.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Performance Metrics", + "changed_path": "slides[3].objects[0].text_runs[0].text", + "checklist_item_id": "slide-03.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[3].layout_ref", + "checklist_item_id": "slide-03.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[3].objects[0]", + "checklist_item_id": "slide-03.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.native-primary", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[3].ssim", + "checklist_item_id": "slide-03.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[3].objects[0]", + "checklist_item_id": "slide-03.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.semantic-structure", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[3].ssim", + "checklist_item_id": "slide-03.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[3].ssim", + "checklist_item_id": "slide-03.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-03.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[4].objects[2]", + "checklist_item_id": "slide-04.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[4].objects[2]", + "checklist_item_id": "slide-04.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[4].ssim", + "checklist_item_id": "slide-04.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 4 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[4].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-04.font-policy", + "expected_negative_affected_slides": [ + 4 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[4].ssim", + "checklist_item_id": "slide-04.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[4].objects[2]", + "checklist_item_id": "slide-04.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Revenue Growth", + "changed_path": "slides[4].objects[0].text_runs[0].text", + "checklist_item_id": "slide-04.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[4].objects[0]", + "checklist_item_id": "slide-04.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[4].objects[0]", + "checklist_item_id": "slide-04.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[4].ssim", + "checklist_item_id": "slide-04.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[4].objects[0]", + "checklist_item_id": "slide-04.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[4].ssim", + "checklist_item_id": "slide-04.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[4].ssim", + "checklist_item_id": "slide-04.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-04.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[5].objects[11]", + "checklist_item_id": "slide-05.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[5].objects[11]", + "checklist_item_id": "slide-05.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[5].ssim", + "checklist_item_id": "slide-05.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 5 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[5].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-05.font-policy", + "expected_negative_affected_slides": [ + 5 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[5].ssim", + "checklist_item_id": "slide-05.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[5].objects[11]", + "checklist_item_id": "slide-05.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Our Team", + "changed_path": "slides[5].objects[0].text_runs[0].text", + "checklist_item_id": "slide-05.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[5].objects[0]", + "checklist_item_id": "slide-05.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[5].objects[2]", + "checklist_item_id": "slide-05.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.native-primary", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[5].ssim", + "checklist_item_id": "slide-05.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[5].objects[2]", + "checklist_item_id": "slide-05.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[5].ssim", + "checklist_item_id": "slide-05.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[5].ssim", + "checklist_item_id": "slide-05.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-05.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[6].objects[5]", + "checklist_item_id": "slide-06.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[6].objects[5]", + "checklist_item_id": "slide-06.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[6].ssim", + "checklist_item_id": "slide-06.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 6 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[6].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-06.font-policy", + "expected_negative_affected_slides": [ + 6 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[6].ssim", + "checklist_item_id": "slide-06.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[6].objects[5]", + "checklist_item_id": "slide-06.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Global Perspectives", + "changed_path": "slides[6].objects[0].text_runs[0].text", + "checklist_item_id": "slide-06.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[6].layout_ref", + "checklist_item_id": "slide-06.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[6].objects[3]", + "checklist_item_id": "slide-06.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[6].ssim", + "checklist_item_id": "slide-06.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[6].objects[3]", + "checklist_item_id": "slide-06.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[6].ssim", + "checklist_item_id": "slide-06.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[6].ssim", + "checklist_item_id": "slide-06.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-06.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[7].objects[4]", + "checklist_item_id": "slide-07.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[7].objects[4]", + "checklist_item_id": "slide-07.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[7].ssim", + "checklist_item_id": "slide-07.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 7 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[7].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-07.font-policy", + "expected_negative_affected_slides": [ + 7 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[7].ssim", + "checklist_item_id": "slide-07.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[7].objects[4]", + "checklist_item_id": "slide-07.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Image Handling", + "changed_path": "slides[7].objects[0].text_runs[0].text", + "checklist_item_id": "slide-07.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[7].layout_ref", + "checklist_item_id": "slide-07.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "0000000000000000000000000000000000000000000000000000000000000000", + "before": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "changed_path": "media_hashes[ppt/media/fixture.bin]", + "checklist_item_id": "slide-07.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[7].ssim", + "checklist_item_id": "slide-07.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[7].objects[2]", + "checklist_item_id": "slide-07.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[7].ssim", + "checklist_item_id": "slide-07.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[7].ssim", + "checklist_item_id": "slide-07.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-07.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[8].objects[5]", + "checklist_item_id": "slide-08.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[8].objects[5]", + "checklist_item_id": "slide-08.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[8].ssim", + "checklist_item_id": "slide-08.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 8 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[8].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-08.font-policy", + "expected_negative_affected_slides": [ + 8 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[8].ssim", + "checklist_item_id": "slide-08.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[8].objects[5]", + "checklist_item_id": "slide-08.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Depth & Layering", + "changed_path": "slides[8].objects[0].text_runs[0].text", + "checklist_item_id": "slide-08.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[8].layout_ref", + "checklist_item_id": "slide-08.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[8].objects[1]", + "checklist_item_id": "slide-08.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.native-primary", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[8].ssim", + "checklist_item_id": "slide-08.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[8].objects[1]", + "checklist_item_id": "slide-08.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[8].ssim", + "checklist_item_id": "slide-08.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[8].ssim", + "checklist_item_id": "slide-08.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-08.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[9].objects[3]", + "checklist_item_id": "slide-09.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[9].objects[3]", + "checklist_item_id": "slide-09.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[9].ssim", + "checklist_item_id": "slide-09.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 9 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[9].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-09.font-policy", + "expected_negative_affected_slides": [ + 9 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[9].ssim", + "checklist_item_id": "slide-09.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[9].objects[3]", + "checklist_item_id": "slide-09.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "API Reference", + "changed_path": "slides[9].objects[0].text_runs[0].text", + "checklist_item_id": "slide-09.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[9].objects[0]", + "checklist_item_id": "slide-09.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[9].objects[1]", + "checklist_item_id": "slide-09.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[9].ssim", + "checklist_item_id": "slide-09.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[9].objects[1]", + "checklist_item_id": "slide-09.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[9].ssim", + "checklist_item_id": "slide-09.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[9].ssim", + "checklist_item_id": "slide-09.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-09.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[10].objects[2]", + "checklist_item_id": "slide-10.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.composition", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[10].objects[2]", + "checklist_item_id": "slide-10.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.decorative-detail", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[10].ssim", + "checklist_item_id": "slide-10.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 10 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[10].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-10.font-policy", + "expected_negative_affected_slides": [ + 10 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[10].ssim", + "checklist_item_id": "slide-10.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[10].objects[2]", + "checklist_item_id": "slide-10.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.hierarchy-z-order", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "System Architecture", + "changed_path": "slides[10].objects[0].text_runs[0].text", + "checklist_item_id": "slide-10.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[10].layout_ref", + "checklist_item_id": "slide-10.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[10].objects[6]", + "checklist_item_id": "slide-10.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.native-primary", + "mutation_operator": "decrement-connector-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[10].ssim", + "checklist_item_id": "slide-10.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[10].objects[6]", + "checklist_item_id": "slide-10.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.semantic-structure", + "mutation_operator": "decrement-connector-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[10].ssim", + "checklist_item_id": "slide-10.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[10].ssim", + "checklist_item_id": "slide-10.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-10.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[11].objects[8]", + "checklist_item_id": "slide-11.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[11].objects[8]", + "checklist_item_id": "slide-11.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[11].ssim", + "checklist_item_id": "slide-11.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 11 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[11].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-11.font-policy", + "expected_negative_affected_slides": [ + 11 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[11].ssim", + "checklist_item_id": "slide-11.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[11].objects[8]", + "checklist_item_id": "slide-11.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Brand Colors", + "changed_path": "slides[11].objects[0].text_runs[0].text", + "checklist_item_id": "slide-11.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[11].objects[0]", + "checklist_item_id": "slide-11.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[11].objects[5]", + "checklist_item_id": "slide-11.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[11].ssim", + "checklist_item_id": "slide-11.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[11].objects[5]", + "checklist_item_id": "slide-11.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[11].ssim", + "checklist_item_id": "slide-11.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[11].ssim", + "checklist_item_id": "slide-11.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-11.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[12].objects[5]", + "checklist_item_id": "slide-12.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[12].objects[5]", + "checklist_item_id": "slide-12.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[12].ssim", + "checklist_item_id": "slide-12.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 12 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[12].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-12.font-policy", + "expected_negative_affected_slides": [ + 12 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[12].ssim", + "checklist_item_id": "slide-12.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[12].objects[5]", + "checklist_item_id": "slide-12.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Document Fields", + "changed_path": "slides[12].objects[0].text_runs[0].text", + "checklist_item_id": "slide-12.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[12].objects[0]", + "checklist_item_id": "slide-12.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[12].objects[1]", + "checklist_item_id": "slide-12.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.native-primary", + "mutation_operator": "decrement-field-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[12].ssim", + "checklist_item_id": "slide-12.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[12].objects[1]", + "checklist_item_id": "slide-12.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.semantic-structure", + "mutation_operator": "decrement-field-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[12].ssim", + "checklist_item_id": "slide-12.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[12].ssim", + "checklist_item_id": "slide-12.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-12.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[13].objects[0]", + "checklist_item_id": "slide-13.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.composition", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[13].objects[0]", + "checklist_item_id": "slide-13.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.decorative-detail", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[13].ssim", + "checklist_item_id": "slide-13.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 13 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[13].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-13.font-policy", + "expected_negative_affected_slides": [ + 13 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[13].ssim", + "checklist_item_id": "slide-13.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[13].objects[0]", + "checklist_item_id": "slide-13.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Composite Stress", + "changed_path": "slides[13].objects[0].text_runs[0].text", + "checklist_item_id": "slide-13.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[13].layout_ref", + "checklist_item_id": "slide-13.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[13].objects[0]", + "checklist_item_id": "slide-13.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[13].ssim", + "checklist_item_id": "slide-13.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[13].objects[0]", + "checklist_item_id": "slide-13.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[13].ssim", + "checklist_item_id": "slide-13.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[13].ssim", + "checklist_item_id": "slide-13.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-13.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[14].objects[3]", + "checklist_item_id": "slide-14.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[14].objects[3]", + "checklist_item_id": "slide-14.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[14].ssim", + "checklist_item_id": "slide-14.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 14 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[14].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-14.font-policy", + "expected_negative_affected_slides": [ + 14 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[14].ssim", + "checklist_item_id": "slide-14.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[14].objects[3]", + "checklist_item_id": "slide-14.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "RTL Systems Review", + "changed_path": "slides[14].objects[0].text_runs[0].text", + "checklist_item_id": "slide-14.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[14].objects[0]", + "checklist_item_id": "slide-14.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[14].objects[1]", + "checklist_item_id": "slide-14.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[14].ssim", + "checklist_item_id": "slide-14.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[14].objects[1]", + "checklist_item_id": "slide-14.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[14].ssim", + "checklist_item_id": "slide-14.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[14].ssim", + "checklist_item_id": "slide-14.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-14.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[15].objects[9]", + "checklist_item_id": "slide-15.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[15].objects[9]", + "checklist_item_id": "slide-15.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[15].ssim", + "checklist_item_id": "slide-15.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 15 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[15].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-15.font-policy", + "expected_negative_affected_slides": [ + 15 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[15].ssim", + "checklist_item_id": "slide-15.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[15].objects[9]", + "checklist_item_id": "slide-15.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Rotation Atlas", + "changed_path": "slides[15].objects[0].text_runs[0].text", + "checklist_item_id": "slide-15.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[15].layout_ref", + "checklist_item_id": "slide-15.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[15].objects[9]", + "checklist_item_id": "slide-15.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[15].ssim", + "checklist_item_id": "slide-15.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[15].objects[9]", + "checklist_item_id": "slide-15.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[15].ssim", + "checklist_item_id": "slide-15.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[15].ssim", + "checklist_item_id": "slide-15.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-15.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[16].objects[4]", + "checklist_item_id": "slide-16.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[16].objects[4]", + "checklist_item_id": "slide-16.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[16].ssim", + "checklist_item_id": "slide-16.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 16 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[16].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-16.font-policy", + "expected_negative_affected_slides": [ + 16 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[16].ssim", + "checklist_item_id": "slide-16.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[16].objects[4]", + "checklist_item_id": "slide-16.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Beyond the Frame", + "changed_path": "slides[16].objects[0].text_runs[0].text", + "checklist_item_id": "slide-16.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[16].layout_ref", + "checklist_item_id": "slide-16.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[16].objects[2]", + "checklist_item_id": "slide-16.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[16].ssim", + "checklist_item_id": "slide-16.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[16].objects[2]", + "checklist_item_id": "slide-16.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[16].ssim", + "checklist_item_id": "slide-16.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[16].ssim", + "checklist_item_id": "slide-16.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-16.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[17].objects[17]", + "checklist_item_id": "slide-17.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[17].objects[17]", + "checklist_item_id": "slide-17.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[17].ssim", + "checklist_item_id": "slide-17.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 17 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[17].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-17.font-policy", + "expected_negative_affected_slides": [ + 17 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[17].ssim", + "checklist_item_id": "slide-17.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[17].objects[17]", + "checklist_item_id": "slide-17.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Nested Systems", + "changed_path": "slides[17].objects[0].text_runs[0].text", + "checklist_item_id": "slide-17.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[17].layout_ref", + "checklist_item_id": "slide-17.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[17].objects[5]", + "checklist_item_id": "slide-17.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.native-primary", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[17].ssim", + "checklist_item_id": "slide-17.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[17].objects[5]", + "checklist_item_id": "slide-17.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[17].ssim", + "checklist_item_id": "slide-17.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[17].ssim", + "checklist_item_id": "slide-17.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-17.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[18].objects[8]", + "checklist_item_id": "slide-18.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[18].objects[8]", + "checklist_item_id": "slide-18.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[18].ssim", + "checklist_item_id": "slide-18.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 18 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[18].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-18.font-policy", + "expected_negative_affected_slides": [ + 18 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[18].ssim", + "checklist_item_id": "slide-18.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[18].objects[8]", + "checklist_item_id": "slide-18.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Three Cities / 三つの都市", + "changed_path": "slides[18].objects[0].text_runs[0].text", + "checklist_item_id": "slide-18.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[18].layout_ref", + "checklist_item_id": "slide-18.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "0000000000000000000000000000000000000000000000000000000000000000", + "before": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385", + "changed_path": "media_hashes[ppt/media/fixture.bin]", + "checklist_item_id": "slide-18.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[18].ssim", + "checklist_item_id": "slide-18.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[18].objects[2]", + "checklist_item_id": "slide-18.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[18].ssim", + "checklist_item_id": "slide-18.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[18].ssim", + "checklist_item_id": "slide-18.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-18.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[19].objects[7]", + "checklist_item_id": "slide-19.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.composition", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[19].objects[7]", + "checklist_item_id": "slide-19.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[19].ssim", + "checklist_item_id": "slide-19.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 19 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[19].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-19.font-policy", + "expected_negative_affected_slides": [ + 19 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[19].ssim", + "checklist_item_id": "slide-19.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[19].objects[7]", + "checklist_item_id": "slide-19.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "Design System Audit", + "changed_path": "slides[19].objects[0].text_runs[0].text", + "checklist_item_id": "slide-19.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "required placeholder", + "changed_path": "slides[19].objects[0]", + "checklist_item_id": "slide-19.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[19].objects[4]", + "checklist_item_id": "slide-19.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[19].ssim", + "checklist_item_id": "slide-19.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[19].objects[4]", + "checklist_item_id": "slide-19.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[19].ssim", + "checklist_item_id": "slide-19.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[19].ssim", + "checklist_item_id": "slide-19.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-19.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[20].objects[0]", + "checklist_item_id": "slide-20.composition", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.composition", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[20].objects[0]", + "checklist_item_id": "slide-20.decorative-detail", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.decorative-detail", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[20].ssim", + "checklist_item_id": "slide-20.focal-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [ + 20 + ], + "after": "Arial", + "before": "Carlito", + "changed_path": "slides[20].objects[0].text_runs[0].font_family", + "checklist_item_id": "slide-20.font-policy", + "expected_negative_affected_slides": [ + 20 + ], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[20].ssim", + "checklist_item_id": "slide-20.full-slide-fidelity", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[20].objects[0]", + "checklist_item_id": "slide-20.hierarchy-z-order", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "single-fault replacement", + "before": "AcidSlide Synthesis", + "changed_path": "slides[20].objects[0].text_runs[0].text", + "checklist_item_id": "slide-20.key-text", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.key-text", + "mutation_operator": "replace-required-text", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "", + "before": "../slideLayouts/slideLayout1.xml", + "changed_path": "slides[20].layout_ref", + "checklist_item_id": "slide-20.layout-binding", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[20].objects[0]", + "checklist_item_id": "slide-20.native-primary", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[20].ssim", + "checklist_item_id": "slide-20.palette", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": "removed", + "before": "present", + "changed_path": "slides[20].objects[0]", + "checklist_item_id": "slide-20.semantic-structure", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[20].ssim", + "checklist_item_id": "slide-20.spacing", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + }, + { + "actual_negative_affected_slides": [], + "after": 0.9998, + "before": 1.0, + "changed_path": "visual_results[20].ssim", + "checklist_item_id": "slide-20.typography", + "expected_negative_affected_slides": [], + "mutant_killed": true, + "mutation_expectation_id": "mutation.slide-20.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_passed": false, + "positive_passed": true + } + ], + "schema_version": "1.0", + "summary": { + "assertion_evidence_completed_by_this_run": 0, + "candidate_items": 280, + "executed_positive_fixtures": 280, + "executed_single_fault_negative_fixtures": 280, + "killed_mutants": 280, + "survived_mutants": 0, + "unimplemented_items": 0 + }, + "unimplemented": [] +} diff --git a/acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json b/acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json new file mode 100644 index 0000000..c6ff2ad --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json @@ -0,0 +1,5080 @@ +{ + "candidate_contract_sha256": "sha256:0cf8a16c4d3bad54c495b35b2c1221b6b9f7d4ef520c4074b513cbf7d4822217", + "entries": [ + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-alignment-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.alignment-detail", + "mutation_expectation_id": "mutation.deck.alignment-detail", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.alignment-detail.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.alignment-detail.single-fault-negative", + "slide": null, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-approved-assets", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.approved-assets", + "mutation_expectation_id": "mutation.deck.approved-assets", + "mutation_operator": "replace-one-approved-asset-hash", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.approved-assets.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "asset_manifest", + "single_fault_negative_fixture_id": "fixture.deck.approved-assets.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "hash_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-cross-slide-hierarchy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.cross-slide-hierarchy", + "mutation_expectation_id": "mutation.deck.cross-slide-hierarchy", + "mutation_operator": "decrement-master-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.cross-slide-hierarchy.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "master_count", + "single_fault_negative_fixture_id": "fixture.deck.cross-slide-hierarchy.single-fault-negative", + "slide": null, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-effect-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.effect-detail", + "mutation_expectation_id": "mutation.deck.effect-detail", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.effect-detail.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.effect-detail.single-fault-negative", + "slide": null, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.font-policy", + "mutation_expectation_id": "mutation.deck.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.font-policy.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.deck.font-policy.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-layouts-defined", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.layouts-defined", + "mutation_expectation_id": "mutation.deck.layouts-defined", + "mutation_operator": "decrement-layout-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.layouts-defined.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "layout_count", + "single_fault_negative_fixture_id": "fixture.deck.layouts-defined.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-line-weight-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.line-weight-detail", + "mutation_expectation_id": "mutation.deck.line-weight-detail", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.line-weight-detail.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.line-weight-detail.single-fault-negative", + "slide": null, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-master-present", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.master-present", + "mutation_expectation_id": "mutation.deck.master-present", + "mutation_operator": "decrement-master-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.master-present.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "master_count", + "single_fault_negative_fixture_id": "fixture.deck.master-present.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-master-visual-consistency", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.master-visual-consistency", + "mutation_expectation_id": "mutation.deck.master-visual-consistency", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.master-visual-consistency.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.master-visual-consistency.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-native-object-coverage", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.native-object-coverage", + "mutation_expectation_id": "mutation.deck.native-object-coverage", + "mutation_operator": "change-exact-slide-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.native-object-coverage.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "slide_count", + "single_fault_negative_fixture_id": "fixture.deck.native-object-coverage.single-fault-negative", + "slide": null, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-native-slide-numbers", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.native-slide-numbers", + "mutation_expectation_id": "mutation.deck.native-slide-numbers", + "mutation_operator": "decrement-master-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.native-slide-numbers.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "master_count", + "single_fault_negative_fixture_id": "fixture.deck.native-slide-numbers.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-no-notes", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.no-notes", + "mutation_expectation_id": "mutation.deck.no-notes", + "mutation_operator": "add-speaker-notes-relationship", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.no-notes.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "no_notes", + "single_fault_negative_fixture_id": "fixture.deck.no-notes.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-ordered-tier-prefix", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.ordered-tier-prefix", + "mutation_expectation_id": "mutation.deck.ordered-tier-prefix", + "mutation_operator": "change-exact-slide-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.ordered-tier-prefix.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "slide_count", + "single_fault_negative_fixture_id": "fixture.deck.ordered-tier-prefix.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-palette-consistency", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.palette-consistency", + "mutation_expectation_id": "mutation.deck.palette-consistency", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.palette-consistency.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.palette-consistency.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-render-consistency", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.render-consistency", + "mutation_expectation_id": "mutation.deck.render-consistency", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.render-consistency.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.render-consistency.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-rtl-cjk-coverage", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.rtl-cjk-coverage", + "mutation_expectation_id": "mutation.deck.rtl-cjk-coverage", + "mutation_operator": "change-exact-slide-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.rtl-cjk-coverage.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "slide_count", + "single_fault_negative_fixture_id": "fixture.deck.rtl-cjk-coverage.single-fault-negative", + "slide": null, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-slide-count", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.slide-count", + "mutation_expectation_id": "mutation.deck.slide-count", + "mutation_operator": "change-exact-slide-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.slide-count.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "slide_count", + "single_fault_negative_fixture_id": "fixture.deck.slide-count.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-spacing-consistency", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.spacing-consistency", + "mutation_expectation_id": "mutation.deck.spacing-consistency", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.spacing-consistency.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.spacing-consistency.single-fault-negative", + "slide": null, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-theme-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.theme-structure", + "mutation_expectation_id": "mutation.deck.theme-structure", + "mutation_operator": "decrement-master-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.theme-structure.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "master_count", + "single_fault_negative_fixture_id": "fixture.deck.theme-structure.single-fault-negative", + "slide": null, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "deck.assert-typography-consistency", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "deck.typography-consistency", + "mutation_expectation_id": "mutation.deck.typography-consistency", + "mutation_operator": "lower-one-slide-ssim", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.deck.typography-consistency.positive", + "release_evidence_claimed": false, + "scope": "deck", + "selector": "all_slides", + "single_fault_negative_fixture_id": "fixture.deck.typography-consistency.single-fault-negative", + "slide": null, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.composition", + "mutation_expectation_id": "mutation.slide-01.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-01.composition.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.decorative-detail", + "mutation_expectation_id": "mutation.slide-01.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-01.decorative-detail.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.focal-fidelity", + "mutation_expectation_id": "mutation.slide-01.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-01.focal-fidelity.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.font-policy", + "mutation_expectation_id": "mutation.slide-01.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-01.font-policy.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-01.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-01.full-slide-fidelity.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-01.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-01.hierarchy-z-order.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.key-text", + "mutation_expectation_id": "mutation.slide-01.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-01.key-text.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.layout-binding", + "mutation_expectation_id": "mutation.slide-01.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-01.layout-binding.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.native-primary", + "mutation_expectation_id": "mutation.slide-01.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "approved_asset", + "single_fault_negative_fixture_id": "fixture.slide-01.native-primary.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "hash_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.palette", + "mutation_expectation_id": "mutation.slide-01.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-01.palette.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.semantic-structure", + "mutation_expectation_id": "mutation.slide-01.semantic-structure", + "mutation_operator": "decrement-picture-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "picture", + "single_fault_negative_fixture_id": "fixture.slide-01.semantic-structure.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.spacing", + "mutation_expectation_id": "mutation.slide-01.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-01.spacing.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-01.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-01.typography", + "mutation_expectation_id": "mutation.slide-01.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-01.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-01.typography.single-fault-negative", + "slide": 1, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.composition", + "mutation_expectation_id": "mutation.slide-02.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-02.composition.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.decorative-detail", + "mutation_expectation_id": "mutation.slide-02.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-02.decorative-detail.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.focal-fidelity", + "mutation_expectation_id": "mutation.slide-02.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-02.focal-fidelity.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.font-policy", + "mutation_expectation_id": "mutation.slide-02.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-02.font-policy.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-02.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-02.full-slide-fidelity.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-02.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-02.hierarchy-z-order.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.key-text", + "mutation_expectation_id": "mutation.slide-02.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-02.key-text.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.layout-binding", + "mutation_expectation_id": "mutation.slide-02.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-02.layout-binding.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.native-primary", + "mutation_expectation_id": "mutation.slide-02.native-primary", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-02.native-primary.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.palette", + "mutation_expectation_id": "mutation.slide-02.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-02.palette.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.semantic-structure", + "mutation_expectation_id": "mutation.slide-02.semantic-structure", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-02.semantic-structure.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.spacing", + "mutation_expectation_id": "mutation.slide-02.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-02.spacing.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-02.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-02.typography", + "mutation_expectation_id": "mutation.slide-02.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-02.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-02.typography.single-fault-negative", + "slide": 2, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.composition", + "mutation_expectation_id": "mutation.slide-03.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-03.composition.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.decorative-detail", + "mutation_expectation_id": "mutation.slide-03.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-03.decorative-detail.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.focal-fidelity", + "mutation_expectation_id": "mutation.slide-03.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-03.focal-fidelity.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.font-policy", + "mutation_expectation_id": "mutation.slide-03.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-03.font-policy.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-03.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-03.full-slide-fidelity.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-03.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-03.hierarchy-z-order.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.key-text", + "mutation_expectation_id": "mutation.slide-03.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-03.key-text.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.layout-binding", + "mutation_expectation_id": "mutation.slide-03.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-03.layout-binding.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.native-primary", + "mutation_expectation_id": "mutation.slide-03.native-primary", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-03.native-primary.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.palette", + "mutation_expectation_id": "mutation.slide-03.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-03.palette.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.semantic-structure", + "mutation_expectation_id": "mutation.slide-03.semantic-structure", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-03.semantic-structure.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.spacing", + "mutation_expectation_id": "mutation.slide-03.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-03.spacing.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-03.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-03.typography", + "mutation_expectation_id": "mutation.slide-03.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-03.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-03.typography.single-fault-negative", + "slide": 3, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.composition", + "mutation_expectation_id": "mutation.slide-04.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-04.composition.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.decorative-detail", + "mutation_expectation_id": "mutation.slide-04.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-04.decorative-detail.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.focal-fidelity", + "mutation_expectation_id": "mutation.slide-04.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-04.focal-fidelity.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.font-policy", + "mutation_expectation_id": "mutation.slide-04.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-04.font-policy.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-04.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-04.full-slide-fidelity.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-04.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-04.hierarchy-z-order.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.key-text", + "mutation_expectation_id": "mutation.slide-04.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-04.key-text.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.layout-binding", + "mutation_expectation_id": "mutation.slide-04.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-04.layout-binding.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.native-primary", + "mutation_expectation_id": "mutation.slide-04.native-primary", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-04.native-primary.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.palette", + "mutation_expectation_id": "mutation.slide-04.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-04.palette.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.semantic-structure", + "mutation_expectation_id": "mutation.slide-04.semantic-structure", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-04.semantic-structure.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.spacing", + "mutation_expectation_id": "mutation.slide-04.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-04.spacing.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-04.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-04.typography", + "mutation_expectation_id": "mutation.slide-04.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-04.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-04.typography.single-fault-negative", + "slide": 4, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.composition", + "mutation_expectation_id": "mutation.slide-05.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-05.composition.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.decorative-detail", + "mutation_expectation_id": "mutation.slide-05.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-05.decorative-detail.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.focal-fidelity", + "mutation_expectation_id": "mutation.slide-05.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-05.focal-fidelity.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.font-policy", + "mutation_expectation_id": "mutation.slide-05.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-05.font-policy.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-05.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-05.full-slide-fidelity.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-05.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-05.hierarchy-z-order.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.key-text", + "mutation_expectation_id": "mutation.slide-05.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-05.key-text.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.layout-binding", + "mutation_expectation_id": "mutation.slide-05.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-05.layout-binding.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.native-primary", + "mutation_expectation_id": "mutation.slide-05.native-primary", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-05.native-primary.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.palette", + "mutation_expectation_id": "mutation.slide-05.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-05.palette.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.semantic-structure", + "mutation_expectation_id": "mutation.slide-05.semantic-structure", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-05.semantic-structure.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.spacing", + "mutation_expectation_id": "mutation.slide-05.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-05.spacing.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-05.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-05.typography", + "mutation_expectation_id": "mutation.slide-05.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-05.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-05.typography.single-fault-negative", + "slide": 5, + "tier": 1, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.composition", + "mutation_expectation_id": "mutation.slide-06.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-06.composition.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.decorative-detail", + "mutation_expectation_id": "mutation.slide-06.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-06.decorative-detail.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.focal-fidelity", + "mutation_expectation_id": "mutation.slide-06.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-06.focal-fidelity.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.font-policy", + "mutation_expectation_id": "mutation.slide-06.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-06.font-policy.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-06.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-06.full-slide-fidelity.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-06.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-06.hierarchy-z-order.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.key-text", + "mutation_expectation_id": "mutation.slide-06.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-06.key-text.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.layout-binding", + "mutation_expectation_id": "mutation.slide-06.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-06.layout-binding.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.native-primary", + "mutation_expectation_id": "mutation.slide-06.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-06.native-primary.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.palette", + "mutation_expectation_id": "mutation.slide-06.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-06.palette.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.semantic-structure", + "mutation_expectation_id": "mutation.slide-06.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-06.semantic-structure.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.spacing", + "mutation_expectation_id": "mutation.slide-06.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-06.spacing.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-06.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-06.typography", + "mutation_expectation_id": "mutation.slide-06.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-06.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-06.typography.single-fault-negative", + "slide": 6, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.composition", + "mutation_expectation_id": "mutation.slide-07.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-07.composition.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.decorative-detail", + "mutation_expectation_id": "mutation.slide-07.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-07.decorative-detail.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.focal-fidelity", + "mutation_expectation_id": "mutation.slide-07.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-07.focal-fidelity.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.font-policy", + "mutation_expectation_id": "mutation.slide-07.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-07.font-policy.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-07.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-07.full-slide-fidelity.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-07.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-07.hierarchy-z-order.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.key-text", + "mutation_expectation_id": "mutation.slide-07.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-07.key-text.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.layout-binding", + "mutation_expectation_id": "mutation.slide-07.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-07.layout-binding.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.native-primary", + "mutation_expectation_id": "mutation.slide-07.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "approved_asset", + "single_fault_negative_fixture_id": "fixture.slide-07.native-primary.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "hash_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.palette", + "mutation_expectation_id": "mutation.slide-07.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-07.palette.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.semantic-structure", + "mutation_expectation_id": "mutation.slide-07.semantic-structure", + "mutation_operator": "decrement-picture-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "picture", + "single_fault_negative_fixture_id": "fixture.slide-07.semantic-structure.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.spacing", + "mutation_expectation_id": "mutation.slide-07.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-07.spacing.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-07.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-07.typography", + "mutation_expectation_id": "mutation.slide-07.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-07.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-07.typography.single-fault-negative", + "slide": 7, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.composition", + "mutation_expectation_id": "mutation.slide-08.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-08.composition.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.decorative-detail", + "mutation_expectation_id": "mutation.slide-08.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-08.decorative-detail.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.focal-fidelity", + "mutation_expectation_id": "mutation.slide-08.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-08.focal-fidelity.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.font-policy", + "mutation_expectation_id": "mutation.slide-08.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-08.font-policy.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-08.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-08.full-slide-fidelity.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-08.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-08.hierarchy-z-order.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.key-text", + "mutation_expectation_id": "mutation.slide-08.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-08.key-text.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.layout-binding", + "mutation_expectation_id": "mutation.slide-08.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-08.layout-binding.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.native-primary", + "mutation_expectation_id": "mutation.slide-08.native-primary", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-08.native-primary.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.palette", + "mutation_expectation_id": "mutation.slide-08.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-08.palette.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.semantic-structure", + "mutation_expectation_id": "mutation.slide-08.semantic-structure", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-08.semantic-structure.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.spacing", + "mutation_expectation_id": "mutation.slide-08.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-08.spacing.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-08.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-08.typography", + "mutation_expectation_id": "mutation.slide-08.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-08.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-08.typography.single-fault-negative", + "slide": 8, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.composition", + "mutation_expectation_id": "mutation.slide-09.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-09.composition.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.decorative-detail", + "mutation_expectation_id": "mutation.slide-09.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-09.decorative-detail.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.focal-fidelity", + "mutation_expectation_id": "mutation.slide-09.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-09.focal-fidelity.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.font-policy", + "mutation_expectation_id": "mutation.slide-09.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-09.font-policy.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-09.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-09.full-slide-fidelity.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-09.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-09.hierarchy-z-order.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.key-text", + "mutation_expectation_id": "mutation.slide-09.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-09.key-text.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.layout-binding", + "mutation_expectation_id": "mutation.slide-09.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-09.layout-binding.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.native-primary", + "mutation_expectation_id": "mutation.slide-09.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-09.native-primary.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.palette", + "mutation_expectation_id": "mutation.slide-09.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-09.palette.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.semantic-structure", + "mutation_expectation_id": "mutation.slide-09.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-09.semantic-structure.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.spacing", + "mutation_expectation_id": "mutation.slide-09.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-09.spacing.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-09.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-09.typography", + "mutation_expectation_id": "mutation.slide-09.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-09.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-09.typography.single-fault-negative", + "slide": 9, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.composition", + "mutation_expectation_id": "mutation.slide-10.composition", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-10.composition.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.decorative-detail", + "mutation_expectation_id": "mutation.slide-10.decorative-detail", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-10.decorative-detail.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.focal-fidelity", + "mutation_expectation_id": "mutation.slide-10.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-10.focal-fidelity.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.font-policy", + "mutation_expectation_id": "mutation.slide-10.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-10.font-policy.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-10.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-10.full-slide-fidelity.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-10.hierarchy-z-order", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-10.hierarchy-z-order.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.key-text", + "mutation_expectation_id": "mutation.slide-10.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-10.key-text.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.layout-binding", + "mutation_expectation_id": "mutation.slide-10.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-10.layout-binding.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.native-primary", + "mutation_expectation_id": "mutation.slide-10.native-primary", + "mutation_operator": "decrement-connector-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "connector", + "single_fault_negative_fixture_id": "fixture.slide-10.native-primary.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.palette", + "mutation_expectation_id": "mutation.slide-10.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-10.palette.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.semantic-structure", + "mutation_expectation_id": "mutation.slide-10.semantic-structure", + "mutation_operator": "decrement-connector-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "connector", + "single_fault_negative_fixture_id": "fixture.slide-10.semantic-structure.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.spacing", + "mutation_expectation_id": "mutation.slide-10.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-10.spacing.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-10.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-10.typography", + "mutation_expectation_id": "mutation.slide-10.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-10.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-10.typography.single-fault-negative", + "slide": 10, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.composition", + "mutation_expectation_id": "mutation.slide-11.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-11.composition.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.decorative-detail", + "mutation_expectation_id": "mutation.slide-11.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-11.decorative-detail.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.focal-fidelity", + "mutation_expectation_id": "mutation.slide-11.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-11.focal-fidelity.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.font-policy", + "mutation_expectation_id": "mutation.slide-11.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-11.font-policy.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-11.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-11.full-slide-fidelity.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-11.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-11.hierarchy-z-order.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.key-text", + "mutation_expectation_id": "mutation.slide-11.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-11.key-text.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.layout-binding", + "mutation_expectation_id": "mutation.slide-11.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-11.layout-binding.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.native-primary", + "mutation_expectation_id": "mutation.slide-11.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-11.native-primary.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.palette", + "mutation_expectation_id": "mutation.slide-11.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-11.palette.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.semantic-structure", + "mutation_expectation_id": "mutation.slide-11.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-11.semantic-structure.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.spacing", + "mutation_expectation_id": "mutation.slide-11.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-11.spacing.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-11.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-11.typography", + "mutation_expectation_id": "mutation.slide-11.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-11.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-11.typography.single-fault-negative", + "slide": 11, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.composition", + "mutation_expectation_id": "mutation.slide-12.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-12.composition.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.decorative-detail", + "mutation_expectation_id": "mutation.slide-12.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-12.decorative-detail.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.focal-fidelity", + "mutation_expectation_id": "mutation.slide-12.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-12.focal-fidelity.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.font-policy", + "mutation_expectation_id": "mutation.slide-12.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-12.font-policy.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-12.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-12.full-slide-fidelity.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-12.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-12.hierarchy-z-order.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.key-text", + "mutation_expectation_id": "mutation.slide-12.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-12.key-text.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.layout-binding", + "mutation_expectation_id": "mutation.slide-12.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-12.layout-binding.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.native-primary", + "mutation_expectation_id": "mutation.slide-12.native-primary", + "mutation_operator": "decrement-field-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "field", + "single_fault_negative_fixture_id": "fixture.slide-12.native-primary.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.palette", + "mutation_expectation_id": "mutation.slide-12.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-12.palette.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.semantic-structure", + "mutation_expectation_id": "mutation.slide-12.semantic-structure", + "mutation_operator": "decrement-field-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "field", + "single_fault_negative_fixture_id": "fixture.slide-12.semantic-structure.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.spacing", + "mutation_expectation_id": "mutation.slide-12.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-12.spacing.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-12.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-12.typography", + "mutation_expectation_id": "mutation.slide-12.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-12.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-12.typography.single-fault-negative", + "slide": 12, + "tier": 2, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.composition", + "mutation_expectation_id": "mutation.slide-13.composition", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-13.composition.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.decorative-detail", + "mutation_expectation_id": "mutation.slide-13.decorative-detail", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-13.decorative-detail.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.focal-fidelity", + "mutation_expectation_id": "mutation.slide-13.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-13.focal-fidelity.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.font-policy", + "mutation_expectation_id": "mutation.slide-13.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-13.font-policy.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-13.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-13.full-slide-fidelity.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-13.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-13.hierarchy-z-order.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.key-text", + "mutation_expectation_id": "mutation.slide-13.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-13.key-text.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.layout-binding", + "mutation_expectation_id": "mutation.slide-13.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-13.layout-binding.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.native-primary", + "mutation_expectation_id": "mutation.slide-13.native-primary", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-13.native-primary.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.palette", + "mutation_expectation_id": "mutation.slide-13.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-13.palette.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.semantic-structure", + "mutation_expectation_id": "mutation.slide-13.semantic-structure", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-13.semantic-structure.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.spacing", + "mutation_expectation_id": "mutation.slide-13.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-13.spacing.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-13.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-13.typography", + "mutation_expectation_id": "mutation.slide-13.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-13.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-13.typography.single-fault-negative", + "slide": 13, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.composition", + "mutation_expectation_id": "mutation.slide-14.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-14.composition.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.decorative-detail", + "mutation_expectation_id": "mutation.slide-14.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-14.decorative-detail.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.focal-fidelity", + "mutation_expectation_id": "mutation.slide-14.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-14.focal-fidelity.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.font-policy", + "mutation_expectation_id": "mutation.slide-14.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-14.font-policy.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-14.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-14.full-slide-fidelity.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-14.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-14.hierarchy-z-order.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.key-text", + "mutation_expectation_id": "mutation.slide-14.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-14.key-text.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.layout-binding", + "mutation_expectation_id": "mutation.slide-14.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-14.layout-binding.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.native-primary", + "mutation_expectation_id": "mutation.slide-14.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-14.native-primary.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.palette", + "mutation_expectation_id": "mutation.slide-14.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-14.palette.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.semantic-structure", + "mutation_expectation_id": "mutation.slide-14.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-14.semantic-structure.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.spacing", + "mutation_expectation_id": "mutation.slide-14.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-14.spacing.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-14.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-14.typography", + "mutation_expectation_id": "mutation.slide-14.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-14.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-14.typography.single-fault-negative", + "slide": 14, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.composition", + "mutation_expectation_id": "mutation.slide-15.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-15.composition.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.decorative-detail", + "mutation_expectation_id": "mutation.slide-15.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-15.decorative-detail.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.focal-fidelity", + "mutation_expectation_id": "mutation.slide-15.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-15.focal-fidelity.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.font-policy", + "mutation_expectation_id": "mutation.slide-15.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-15.font-policy.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-15.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-15.full-slide-fidelity.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-15.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-15.hierarchy-z-order.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.key-text", + "mutation_expectation_id": "mutation.slide-15.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-15.key-text.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.layout-binding", + "mutation_expectation_id": "mutation.slide-15.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-15.layout-binding.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.native-primary", + "mutation_expectation_id": "mutation.slide-15.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-15.native-primary.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.palette", + "mutation_expectation_id": "mutation.slide-15.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-15.palette.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.semantic-structure", + "mutation_expectation_id": "mutation.slide-15.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-15.semantic-structure.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.spacing", + "mutation_expectation_id": "mutation.slide-15.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-15.spacing.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-15.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-15.typography", + "mutation_expectation_id": "mutation.slide-15.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-15.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-15.typography.single-fault-negative", + "slide": 15, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.composition", + "mutation_expectation_id": "mutation.slide-16.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-16.composition.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.decorative-detail", + "mutation_expectation_id": "mutation.slide-16.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-16.decorative-detail.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.focal-fidelity", + "mutation_expectation_id": "mutation.slide-16.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-16.focal-fidelity.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.font-policy", + "mutation_expectation_id": "mutation.slide-16.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-16.font-policy.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-16.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-16.full-slide-fidelity.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-16.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-16.hierarchy-z-order.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.key-text", + "mutation_expectation_id": "mutation.slide-16.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-16.key-text.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.layout-binding", + "mutation_expectation_id": "mutation.slide-16.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-16.layout-binding.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.native-primary", + "mutation_expectation_id": "mutation.slide-16.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-16.native-primary.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.palette", + "mutation_expectation_id": "mutation.slide-16.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-16.palette.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.semantic-structure", + "mutation_expectation_id": "mutation.slide-16.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-16.semantic-structure.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.spacing", + "mutation_expectation_id": "mutation.slide-16.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-16.spacing.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-16.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-16.typography", + "mutation_expectation_id": "mutation.slide-16.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-16.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-16.typography.single-fault-negative", + "slide": 16, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.composition", + "mutation_expectation_id": "mutation.slide-17.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-17.composition.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.decorative-detail", + "mutation_expectation_id": "mutation.slide-17.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-17.decorative-detail.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.focal-fidelity", + "mutation_expectation_id": "mutation.slide-17.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-17.focal-fidelity.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.font-policy", + "mutation_expectation_id": "mutation.slide-17.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-17.font-policy.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-17.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-17.full-slide-fidelity.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-17.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-17.hierarchy-z-order.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.key-text", + "mutation_expectation_id": "mutation.slide-17.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-17.key-text.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.layout-binding", + "mutation_expectation_id": "mutation.slide-17.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-17.layout-binding.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.native-primary", + "mutation_expectation_id": "mutation.slide-17.native-primary", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-17.native-primary.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.palette", + "mutation_expectation_id": "mutation.slide-17.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-17.palette.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.semantic-structure", + "mutation_expectation_id": "mutation.slide-17.semantic-structure", + "mutation_operator": "decrement-group-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "group", + "single_fault_negative_fixture_id": "fixture.slide-17.semantic-structure.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.spacing", + "mutation_expectation_id": "mutation.slide-17.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-17.spacing.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-17.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-17.typography", + "mutation_expectation_id": "mutation.slide-17.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-17.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-17.typography.single-fault-negative", + "slide": 17, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.composition", + "mutation_expectation_id": "mutation.slide-18.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-18.composition.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.decorative-detail", + "mutation_expectation_id": "mutation.slide-18.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-18.decorative-detail.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.focal-fidelity", + "mutation_expectation_id": "mutation.slide-18.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-18.focal-fidelity.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.font-policy", + "mutation_expectation_id": "mutation.slide-18.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-18.font-policy.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-18.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-18.full-slide-fidelity.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-18.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-18.hierarchy-z-order.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.key-text", + "mutation_expectation_id": "mutation.slide-18.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-18.key-text.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.layout-binding", + "mutation_expectation_id": "mutation.slide-18.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-18.layout-binding.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.native-primary", + "mutation_expectation_id": "mutation.slide-18.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "approved_asset", + "single_fault_negative_fixture_id": "fixture.slide-18.native-primary.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "hash_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.palette", + "mutation_expectation_id": "mutation.slide-18.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-18.palette.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.semantic-structure", + "mutation_expectation_id": "mutation.slide-18.semantic-structure", + "mutation_operator": "decrement-picture-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "picture", + "single_fault_negative_fixture_id": "fixture.slide-18.semantic-structure.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.spacing", + "mutation_expectation_id": "mutation.slide-18.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-18.spacing.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-18.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-18.typography", + "mutation_expectation_id": "mutation.slide-18.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-18.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-18.typography.single-fault-negative", + "slide": 18, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.composition", + "mutation_expectation_id": "mutation.slide-19.composition", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-19.composition.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.decorative-detail", + "mutation_expectation_id": "mutation.slide-19.decorative-detail", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-19.decorative-detail.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.focal-fidelity", + "mutation_expectation_id": "mutation.slide-19.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-19.focal-fidelity.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.font-policy", + "mutation_expectation_id": "mutation.slide-19.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-19.font-policy.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-19.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-19.full-slide-fidelity.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-19.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-19.hierarchy-z-order.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.key-text", + "mutation_expectation_id": "mutation.slide-19.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-19.key-text.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.layout-binding", + "mutation_expectation_id": "mutation.slide-19.layout-binding", + "mutation_operator": "remove-required-placeholder", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "placeholder", + "single_fault_negative_fixture_id": "fixture.slide-19.layout-binding.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.native-primary", + "mutation_expectation_id": "mutation.slide-19.native-primary", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-19.native-primary.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.palette", + "mutation_expectation_id": "mutation.slide-19.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-19.palette.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.semantic-structure", + "mutation_expectation_id": "mutation.slide-19.semantic-structure", + "mutation_operator": "decrement-shape-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "shape", + "single_fault_negative_fixture_id": "fixture.slide-19.semantic-structure.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.spacing", + "mutation_expectation_id": "mutation.slide-19.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-19.spacing.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-19.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-19.typography", + "mutation_expectation_id": "mutation.slide-19.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-19.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-19.typography.single-fault-negative", + "slide": 19, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-composition", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.composition", + "mutation_expectation_id": "mutation.slide-20.composition", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.composition.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-20.composition.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-decorative-detail", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.decorative-detail", + "mutation_expectation_id": "mutation.slide-20.decorative-detail", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.decorative-detail.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-20.decorative-detail.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-focal-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.focal-fidelity", + "mutation_expectation_id": "mutation.slide-20.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.focal-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-20.focal-fidelity.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-font-policy", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.font-policy", + "mutation_expectation_id": "mutation.slide-20.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.font-policy.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "font_policy", + "single_fault_negative_fixture_id": "fixture.slide-20.font-policy.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "anti_cheat" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-full-slide-fidelity", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.full-slide-fidelity", + "mutation_expectation_id": "mutation.slide-20.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.full-slide-fidelity.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-20.full-slide-fidelity.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-hierarchy-z-order", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.hierarchy-z-order", + "mutation_expectation_id": "mutation.slide-20.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.hierarchy-z-order.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "table", + "single_fault_negative_fixture_id": "fixture.slide-20.hierarchy-z-order.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-key-text", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.key-text", + "mutation_expectation_id": "mutation.slide-20.key-text", + "mutation_operator": "replace-required-text", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.key-text.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "slide_text", + "single_fault_negative_fixture_id": "fixture.slide-20.key-text.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "text_match" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-layout-binding", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.layout-binding", + "mutation_expectation_id": "mutation.slide-20.layout-binding", + "mutation_operator": "clear-layout-reference", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.layout-binding.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "master_ref", + "single_fault_negative_fixture_id": "fixture.slide-20.layout-binding.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "layout_check" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-native-primary", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.native-primary", + "mutation_expectation_id": "mutation.slide-20.native-primary", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.native-primary.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-20.native-primary.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-palette", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.palette", + "mutation_expectation_id": "mutation.slide-20.palette", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.palette.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-20.palette.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-semantic-structure", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.semantic-structure", + "mutation_expectation_id": "mutation.slide-20.semantic-structure", + "mutation_operator": "decrement-chart-count", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.semantic-structure.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "chart", + "single_fault_negative_fixture_id": "fixture.slide-20.semantic-structure.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "object_compare" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-spacing", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.spacing", + "mutation_expectation_id": "mutation.slide-20.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.spacing.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-20.spacing.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + }, + { + "assertion_evidence_status": "pending", + "assertion_id": "slide-20.assert-typography", + "assertion_lifecycle_state": "candidate", + "checklist_item_id": "slide-20.typography", + "mutation_expectation_id": "mutation.slide-20.typography", + "mutation_operator": "lower-ssim-below-threshold", + "operator_coverage_status": "executable", + "positive_fixture_id": "fixture.slide-20.typography.positive", + "release_evidence_claimed": false, + "scope": "slide", + "selector": "full_slide", + "single_fault_negative_fixture_id": "fixture.slide-20.typography.single-fault-negative", + "slide": 20, + "tier": 3, + "unresolved_reason": null, + "verification_method": "visual_ssim" + } + ], + "evidence_scope": "generated operator behavior only; not independent assertion provenance, review, or evidence", + "fixture_index_id": "acidslide-generated-mutation-fixture-index-v1", + "schema_version": "1.0", + "source_inventory_id": "acidslide-scored-assertion-inventory-v1", + "summary": { + "assertion_evidence_complete": 0, + "assertion_evidence_pending_or_unknown": 280, + "candidate_items": 280, + "executable_items": 280, + "generated_mutation_expectations": 280, + "generated_positive_fixtures": 280, + "generated_single_fault_negative_fixtures": 280, + "operator_counts": { + "add-speaker-notes-relationship": 1, + "change-exact-slide-count": 4, + "clear-layout-reference": 11, + "decrement-chart-count": 6, + "decrement-connector-count": 2, + "decrement-field-count": 2, + "decrement-group-count": 11, + "decrement-layout-count": 1, + "decrement-master-count": 4, + "decrement-picture-count": 3, + "decrement-shape-count": 65, + "decrement-table-count": 8, + "lower-one-slide-ssim": 8, + "lower-ssim-below-threshold": 100, + "remove-required-placeholder": 9, + "replace-approved-asset-hash": 3, + "replace-one-approved-asset-hash": 1, + "replace-required-text": 20, + "substitute-non-bundled-font": 21 + }, + "unimplemented_items": 0 + } +} diff --git a/acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json b/acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json new file mode 100644 index 0000000..6dae8d9 --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json @@ -0,0 +1,3654 @@ +{ + "evidence_scope": "generated operator behavior only; not independent assertion provenance, review, or evidence", + "expectation_set_id": "acidslide-generated-mutation-expectations-v1", + "expectations": [ + { + "assertion_id": "deck.assert-alignment-detail", + "checklist_item_id": "deck.alignment-detail", + "expected_failed_item_ids": [ + "deck.alignment-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.alignment-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-approved-assets", + "checklist_item_id": "deck.approved-assets", + "expected_failed_item_ids": [ + "deck.approved-assets" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.approved-assets", + "mutation_operator": "replace-one-approved-asset-hash", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-cross-slide-hierarchy", + "checklist_item_id": "deck.cross-slide-hierarchy", + "expected_failed_item_ids": [ + "deck.cross-slide-hierarchy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.cross-slide-hierarchy", + "mutation_operator": "decrement-master-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-effect-detail", + "checklist_item_id": "deck.effect-detail", + "expected_failed_item_ids": [ + "deck.effect-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.effect-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-font-policy", + "checklist_item_id": "deck.font-policy", + "expected_failed_item_ids": [ + "deck.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-layouts-defined", + "checklist_item_id": "deck.layouts-defined", + "expected_failed_item_ids": [ + "deck.layouts-defined" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.layouts-defined", + "mutation_operator": "decrement-layout-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-line-weight-detail", + "checklist_item_id": "deck.line-weight-detail", + "expected_failed_item_ids": [ + "deck.line-weight-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.line-weight-detail", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-master-present", + "checklist_item_id": "deck.master-present", + "expected_failed_item_ids": [ + "deck.master-present" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.master-present", + "mutation_operator": "decrement-master-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-master-visual-consistency", + "checklist_item_id": "deck.master-visual-consistency", + "expected_failed_item_ids": [ + "deck.master-visual-consistency" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.master-visual-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-native-object-coverage", + "checklist_item_id": "deck.native-object-coverage", + "expected_failed_item_ids": [ + "deck.native-object-coverage" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.native-object-coverage", + "mutation_operator": "change-exact-slide-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-native-slide-numbers", + "checklist_item_id": "deck.native-slide-numbers", + "expected_failed_item_ids": [ + "deck.native-slide-numbers" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.native-slide-numbers", + "mutation_operator": "decrement-master-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-no-notes", + "checklist_item_id": "deck.no-notes", + "expected_failed_item_ids": [ + "deck.no-notes" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.no-notes", + "mutation_operator": "add-speaker-notes-relationship", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-ordered-tier-prefix", + "checklist_item_id": "deck.ordered-tier-prefix", + "expected_failed_item_ids": [ + "deck.ordered-tier-prefix" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.ordered-tier-prefix", + "mutation_operator": "change-exact-slide-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-palette-consistency", + "checklist_item_id": "deck.palette-consistency", + "expected_failed_item_ids": [ + "deck.palette-consistency" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.palette-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-render-consistency", + "checklist_item_id": "deck.render-consistency", + "expected_failed_item_ids": [ + "deck.render-consistency" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.render-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-rtl-cjk-coverage", + "checklist_item_id": "deck.rtl-cjk-coverage", + "expected_failed_item_ids": [ + "deck.rtl-cjk-coverage" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.rtl-cjk-coverage", + "mutation_operator": "change-exact-slide-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-slide-count", + "checklist_item_id": "deck.slide-count", + "expected_failed_item_ids": [ + "deck.slide-count" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.slide-count", + "mutation_operator": "change-exact-slide-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-spacing-consistency", + "checklist_item_id": "deck.spacing-consistency", + "expected_failed_item_ids": [ + "deck.spacing-consistency" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.spacing-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-theme-structure", + "checklist_item_id": "deck.theme-structure", + "expected_failed_item_ids": [ + "deck.theme-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.theme-structure", + "mutation_operator": "decrement-master-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "deck.assert-typography-consistency", + "checklist_item_id": "deck.typography-consistency", + "expected_failed_item_ids": [ + "deck.typography-consistency" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.deck.typography-consistency", + "mutation_operator": "lower-one-slide-ssim", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-composition", + "checklist_item_id": "slide-01.composition", + "expected_failed_item_ids": [ + "slide-01.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-decorative-detail", + "checklist_item_id": "slide-01.decorative-detail", + "expected_failed_item_ids": [ + "slide-01.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-focal-fidelity", + "checklist_item_id": "slide-01.focal-fidelity", + "expected_failed_item_ids": [ + "slide-01.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-font-policy", + "checklist_item_id": "slide-01.font-policy", + "expected_failed_item_ids": [ + "slide-01.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-full-slide-fidelity", + "checklist_item_id": "slide-01.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-01.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-hierarchy-z-order", + "checklist_item_id": "slide-01.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-01.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-key-text", + "checklist_item_id": "slide-01.key-text", + "expected_failed_item_ids": [ + "slide-01.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-layout-binding", + "checklist_item_id": "slide-01.layout-binding", + "expected_failed_item_ids": [ + "slide-01.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-native-primary", + "checklist_item_id": "slide-01.native-primary", + "expected_failed_item_ids": [ + "slide-01.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-palette", + "checklist_item_id": "slide-01.palette", + "expected_failed_item_ids": [ + "slide-01.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-semantic-structure", + "checklist_item_id": "slide-01.semantic-structure", + "expected_failed_item_ids": [ + "slide-01.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-spacing", + "checklist_item_id": "slide-01.spacing", + "expected_failed_item_ids": [ + "slide-01.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-01.assert-typography", + "checklist_item_id": "slide-01.typography", + "expected_failed_item_ids": [ + "slide-01.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-01.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-composition", + "checklist_item_id": "slide-02.composition", + "expected_failed_item_ids": [ + "slide-02.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-decorative-detail", + "checklist_item_id": "slide-02.decorative-detail", + "expected_failed_item_ids": [ + "slide-02.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-focal-fidelity", + "checklist_item_id": "slide-02.focal-fidelity", + "expected_failed_item_ids": [ + "slide-02.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-font-policy", + "checklist_item_id": "slide-02.font-policy", + "expected_failed_item_ids": [ + "slide-02.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-full-slide-fidelity", + "checklist_item_id": "slide-02.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-02.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-hierarchy-z-order", + "checklist_item_id": "slide-02.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-02.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-key-text", + "checklist_item_id": "slide-02.key-text", + "expected_failed_item_ids": [ + "slide-02.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-layout-binding", + "checklist_item_id": "slide-02.layout-binding", + "expected_failed_item_ids": [ + "slide-02.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-native-primary", + "checklist_item_id": "slide-02.native-primary", + "expected_failed_item_ids": [ + "slide-02.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.native-primary", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-palette", + "checklist_item_id": "slide-02.palette", + "expected_failed_item_ids": [ + "slide-02.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-semantic-structure", + "checklist_item_id": "slide-02.semantic-structure", + "expected_failed_item_ids": [ + "slide-02.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-spacing", + "checklist_item_id": "slide-02.spacing", + "expected_failed_item_ids": [ + "slide-02.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-02.assert-typography", + "checklist_item_id": "slide-02.typography", + "expected_failed_item_ids": [ + "slide-02.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-02.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-composition", + "checklist_item_id": "slide-03.composition", + "expected_failed_item_ids": [ + "slide-03.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-decorative-detail", + "checklist_item_id": "slide-03.decorative-detail", + "expected_failed_item_ids": [ + "slide-03.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-focal-fidelity", + "checklist_item_id": "slide-03.focal-fidelity", + "expected_failed_item_ids": [ + "slide-03.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-font-policy", + "checklist_item_id": "slide-03.font-policy", + "expected_failed_item_ids": [ + "slide-03.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-full-slide-fidelity", + "checklist_item_id": "slide-03.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-03.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-hierarchy-z-order", + "checklist_item_id": "slide-03.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-03.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-key-text", + "checklist_item_id": "slide-03.key-text", + "expected_failed_item_ids": [ + "slide-03.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-layout-binding", + "checklist_item_id": "slide-03.layout-binding", + "expected_failed_item_ids": [ + "slide-03.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-native-primary", + "checklist_item_id": "slide-03.native-primary", + "expected_failed_item_ids": [ + "slide-03.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.native-primary", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-palette", + "checklist_item_id": "slide-03.palette", + "expected_failed_item_ids": [ + "slide-03.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-semantic-structure", + "checklist_item_id": "slide-03.semantic-structure", + "expected_failed_item_ids": [ + "slide-03.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.semantic-structure", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-spacing", + "checklist_item_id": "slide-03.spacing", + "expected_failed_item_ids": [ + "slide-03.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-03.assert-typography", + "checklist_item_id": "slide-03.typography", + "expected_failed_item_ids": [ + "slide-03.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-03.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-composition", + "checklist_item_id": "slide-04.composition", + "expected_failed_item_ids": [ + "slide-04.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-decorative-detail", + "checklist_item_id": "slide-04.decorative-detail", + "expected_failed_item_ids": [ + "slide-04.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-focal-fidelity", + "checklist_item_id": "slide-04.focal-fidelity", + "expected_failed_item_ids": [ + "slide-04.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-font-policy", + "checklist_item_id": "slide-04.font-policy", + "expected_failed_item_ids": [ + "slide-04.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-full-slide-fidelity", + "checklist_item_id": "slide-04.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-04.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-hierarchy-z-order", + "checklist_item_id": "slide-04.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-04.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-key-text", + "checklist_item_id": "slide-04.key-text", + "expected_failed_item_ids": [ + "slide-04.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-layout-binding", + "checklist_item_id": "slide-04.layout-binding", + "expected_failed_item_ids": [ + "slide-04.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-native-primary", + "checklist_item_id": "slide-04.native-primary", + "expected_failed_item_ids": [ + "slide-04.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-palette", + "checklist_item_id": "slide-04.palette", + "expected_failed_item_ids": [ + "slide-04.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-semantic-structure", + "checklist_item_id": "slide-04.semantic-structure", + "expected_failed_item_ids": [ + "slide-04.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-spacing", + "checklist_item_id": "slide-04.spacing", + "expected_failed_item_ids": [ + "slide-04.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-04.assert-typography", + "checklist_item_id": "slide-04.typography", + "expected_failed_item_ids": [ + "slide-04.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-04.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-composition", + "checklist_item_id": "slide-05.composition", + "expected_failed_item_ids": [ + "slide-05.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-decorative-detail", + "checklist_item_id": "slide-05.decorative-detail", + "expected_failed_item_ids": [ + "slide-05.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-focal-fidelity", + "checklist_item_id": "slide-05.focal-fidelity", + "expected_failed_item_ids": [ + "slide-05.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-font-policy", + "checklist_item_id": "slide-05.font-policy", + "expected_failed_item_ids": [ + "slide-05.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-full-slide-fidelity", + "checklist_item_id": "slide-05.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-05.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-hierarchy-z-order", + "checklist_item_id": "slide-05.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-05.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-key-text", + "checklist_item_id": "slide-05.key-text", + "expected_failed_item_ids": [ + "slide-05.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-layout-binding", + "checklist_item_id": "slide-05.layout-binding", + "expected_failed_item_ids": [ + "slide-05.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-native-primary", + "checklist_item_id": "slide-05.native-primary", + "expected_failed_item_ids": [ + "slide-05.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.native-primary", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-palette", + "checklist_item_id": "slide-05.palette", + "expected_failed_item_ids": [ + "slide-05.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-semantic-structure", + "checklist_item_id": "slide-05.semantic-structure", + "expected_failed_item_ids": [ + "slide-05.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-spacing", + "checklist_item_id": "slide-05.spacing", + "expected_failed_item_ids": [ + "slide-05.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-05.assert-typography", + "checklist_item_id": "slide-05.typography", + "expected_failed_item_ids": [ + "slide-05.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-05.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-composition", + "checklist_item_id": "slide-06.composition", + "expected_failed_item_ids": [ + "slide-06.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-decorative-detail", + "checklist_item_id": "slide-06.decorative-detail", + "expected_failed_item_ids": [ + "slide-06.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-focal-fidelity", + "checklist_item_id": "slide-06.focal-fidelity", + "expected_failed_item_ids": [ + "slide-06.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-font-policy", + "checklist_item_id": "slide-06.font-policy", + "expected_failed_item_ids": [ + "slide-06.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-full-slide-fidelity", + "checklist_item_id": "slide-06.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-06.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-hierarchy-z-order", + "checklist_item_id": "slide-06.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-06.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-key-text", + "checklist_item_id": "slide-06.key-text", + "expected_failed_item_ids": [ + "slide-06.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-layout-binding", + "checklist_item_id": "slide-06.layout-binding", + "expected_failed_item_ids": [ + "slide-06.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-native-primary", + "checklist_item_id": "slide-06.native-primary", + "expected_failed_item_ids": [ + "slide-06.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-palette", + "checklist_item_id": "slide-06.palette", + "expected_failed_item_ids": [ + "slide-06.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-semantic-structure", + "checklist_item_id": "slide-06.semantic-structure", + "expected_failed_item_ids": [ + "slide-06.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-spacing", + "checklist_item_id": "slide-06.spacing", + "expected_failed_item_ids": [ + "slide-06.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-06.assert-typography", + "checklist_item_id": "slide-06.typography", + "expected_failed_item_ids": [ + "slide-06.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-06.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-composition", + "checklist_item_id": "slide-07.composition", + "expected_failed_item_ids": [ + "slide-07.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-decorative-detail", + "checklist_item_id": "slide-07.decorative-detail", + "expected_failed_item_ids": [ + "slide-07.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-focal-fidelity", + "checklist_item_id": "slide-07.focal-fidelity", + "expected_failed_item_ids": [ + "slide-07.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-font-policy", + "checklist_item_id": "slide-07.font-policy", + "expected_failed_item_ids": [ + "slide-07.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-full-slide-fidelity", + "checklist_item_id": "slide-07.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-07.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-hierarchy-z-order", + "checklist_item_id": "slide-07.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-07.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-key-text", + "checklist_item_id": "slide-07.key-text", + "expected_failed_item_ids": [ + "slide-07.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-layout-binding", + "checklist_item_id": "slide-07.layout-binding", + "expected_failed_item_ids": [ + "slide-07.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-native-primary", + "checklist_item_id": "slide-07.native-primary", + "expected_failed_item_ids": [ + "slide-07.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-palette", + "checklist_item_id": "slide-07.palette", + "expected_failed_item_ids": [ + "slide-07.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-semantic-structure", + "checklist_item_id": "slide-07.semantic-structure", + "expected_failed_item_ids": [ + "slide-07.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-spacing", + "checklist_item_id": "slide-07.spacing", + "expected_failed_item_ids": [ + "slide-07.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-07.assert-typography", + "checklist_item_id": "slide-07.typography", + "expected_failed_item_ids": [ + "slide-07.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-07.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-composition", + "checklist_item_id": "slide-08.composition", + "expected_failed_item_ids": [ + "slide-08.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-decorative-detail", + "checklist_item_id": "slide-08.decorative-detail", + "expected_failed_item_ids": [ + "slide-08.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-focal-fidelity", + "checklist_item_id": "slide-08.focal-fidelity", + "expected_failed_item_ids": [ + "slide-08.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-font-policy", + "checklist_item_id": "slide-08.font-policy", + "expected_failed_item_ids": [ + "slide-08.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-full-slide-fidelity", + "checklist_item_id": "slide-08.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-08.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-hierarchy-z-order", + "checklist_item_id": "slide-08.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-08.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-key-text", + "checklist_item_id": "slide-08.key-text", + "expected_failed_item_ids": [ + "slide-08.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-layout-binding", + "checklist_item_id": "slide-08.layout-binding", + "expected_failed_item_ids": [ + "slide-08.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-native-primary", + "checklist_item_id": "slide-08.native-primary", + "expected_failed_item_ids": [ + "slide-08.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.native-primary", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-palette", + "checklist_item_id": "slide-08.palette", + "expected_failed_item_ids": [ + "slide-08.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-semantic-structure", + "checklist_item_id": "slide-08.semantic-structure", + "expected_failed_item_ids": [ + "slide-08.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-spacing", + "checklist_item_id": "slide-08.spacing", + "expected_failed_item_ids": [ + "slide-08.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-08.assert-typography", + "checklist_item_id": "slide-08.typography", + "expected_failed_item_ids": [ + "slide-08.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-08.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-composition", + "checklist_item_id": "slide-09.composition", + "expected_failed_item_ids": [ + "slide-09.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-decorative-detail", + "checklist_item_id": "slide-09.decorative-detail", + "expected_failed_item_ids": [ + "slide-09.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-focal-fidelity", + "checklist_item_id": "slide-09.focal-fidelity", + "expected_failed_item_ids": [ + "slide-09.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-font-policy", + "checklist_item_id": "slide-09.font-policy", + "expected_failed_item_ids": [ + "slide-09.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-full-slide-fidelity", + "checklist_item_id": "slide-09.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-09.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-hierarchy-z-order", + "checklist_item_id": "slide-09.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-09.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-key-text", + "checklist_item_id": "slide-09.key-text", + "expected_failed_item_ids": [ + "slide-09.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-layout-binding", + "checklist_item_id": "slide-09.layout-binding", + "expected_failed_item_ids": [ + "slide-09.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-native-primary", + "checklist_item_id": "slide-09.native-primary", + "expected_failed_item_ids": [ + "slide-09.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-palette", + "checklist_item_id": "slide-09.palette", + "expected_failed_item_ids": [ + "slide-09.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-semantic-structure", + "checklist_item_id": "slide-09.semantic-structure", + "expected_failed_item_ids": [ + "slide-09.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-spacing", + "checklist_item_id": "slide-09.spacing", + "expected_failed_item_ids": [ + "slide-09.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-09.assert-typography", + "checklist_item_id": "slide-09.typography", + "expected_failed_item_ids": [ + "slide-09.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-09.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-composition", + "checklist_item_id": "slide-10.composition", + "expected_failed_item_ids": [ + "slide-10.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.composition", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-decorative-detail", + "checklist_item_id": "slide-10.decorative-detail", + "expected_failed_item_ids": [ + "slide-10.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.decorative-detail", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-focal-fidelity", + "checklist_item_id": "slide-10.focal-fidelity", + "expected_failed_item_ids": [ + "slide-10.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-font-policy", + "checklist_item_id": "slide-10.font-policy", + "expected_failed_item_ids": [ + "slide-10.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-full-slide-fidelity", + "checklist_item_id": "slide-10.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-10.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-hierarchy-z-order", + "checklist_item_id": "slide-10.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-10.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.hierarchy-z-order", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-key-text", + "checklist_item_id": "slide-10.key-text", + "expected_failed_item_ids": [ + "slide-10.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-layout-binding", + "checklist_item_id": "slide-10.layout-binding", + "expected_failed_item_ids": [ + "slide-10.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-native-primary", + "checklist_item_id": "slide-10.native-primary", + "expected_failed_item_ids": [ + "slide-10.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.native-primary", + "mutation_operator": "decrement-connector-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-palette", + "checklist_item_id": "slide-10.palette", + "expected_failed_item_ids": [ + "slide-10.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-semantic-structure", + "checklist_item_id": "slide-10.semantic-structure", + "expected_failed_item_ids": [ + "slide-10.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.semantic-structure", + "mutation_operator": "decrement-connector-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-spacing", + "checklist_item_id": "slide-10.spacing", + "expected_failed_item_ids": [ + "slide-10.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-10.assert-typography", + "checklist_item_id": "slide-10.typography", + "expected_failed_item_ids": [ + "slide-10.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-10.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-composition", + "checklist_item_id": "slide-11.composition", + "expected_failed_item_ids": [ + "slide-11.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-decorative-detail", + "checklist_item_id": "slide-11.decorative-detail", + "expected_failed_item_ids": [ + "slide-11.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-focal-fidelity", + "checklist_item_id": "slide-11.focal-fidelity", + "expected_failed_item_ids": [ + "slide-11.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-font-policy", + "checklist_item_id": "slide-11.font-policy", + "expected_failed_item_ids": [ + "slide-11.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-full-slide-fidelity", + "checklist_item_id": "slide-11.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-11.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-hierarchy-z-order", + "checklist_item_id": "slide-11.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-11.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-key-text", + "checklist_item_id": "slide-11.key-text", + "expected_failed_item_ids": [ + "slide-11.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-layout-binding", + "checklist_item_id": "slide-11.layout-binding", + "expected_failed_item_ids": [ + "slide-11.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-native-primary", + "checklist_item_id": "slide-11.native-primary", + "expected_failed_item_ids": [ + "slide-11.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-palette", + "checklist_item_id": "slide-11.palette", + "expected_failed_item_ids": [ + "slide-11.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-semantic-structure", + "checklist_item_id": "slide-11.semantic-structure", + "expected_failed_item_ids": [ + "slide-11.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-spacing", + "checklist_item_id": "slide-11.spacing", + "expected_failed_item_ids": [ + "slide-11.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-11.assert-typography", + "checklist_item_id": "slide-11.typography", + "expected_failed_item_ids": [ + "slide-11.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-11.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-composition", + "checklist_item_id": "slide-12.composition", + "expected_failed_item_ids": [ + "slide-12.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-decorative-detail", + "checklist_item_id": "slide-12.decorative-detail", + "expected_failed_item_ids": [ + "slide-12.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-focal-fidelity", + "checklist_item_id": "slide-12.focal-fidelity", + "expected_failed_item_ids": [ + "slide-12.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-font-policy", + "checklist_item_id": "slide-12.font-policy", + "expected_failed_item_ids": [ + "slide-12.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-full-slide-fidelity", + "checklist_item_id": "slide-12.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-12.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-hierarchy-z-order", + "checklist_item_id": "slide-12.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-12.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-key-text", + "checklist_item_id": "slide-12.key-text", + "expected_failed_item_ids": [ + "slide-12.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-layout-binding", + "checklist_item_id": "slide-12.layout-binding", + "expected_failed_item_ids": [ + "slide-12.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-native-primary", + "checklist_item_id": "slide-12.native-primary", + "expected_failed_item_ids": [ + "slide-12.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.native-primary", + "mutation_operator": "decrement-field-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-palette", + "checklist_item_id": "slide-12.palette", + "expected_failed_item_ids": [ + "slide-12.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-semantic-structure", + "checklist_item_id": "slide-12.semantic-structure", + "expected_failed_item_ids": [ + "slide-12.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.semantic-structure", + "mutation_operator": "decrement-field-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-spacing", + "checklist_item_id": "slide-12.spacing", + "expected_failed_item_ids": [ + "slide-12.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-12.assert-typography", + "checklist_item_id": "slide-12.typography", + "expected_failed_item_ids": [ + "slide-12.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-12.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-composition", + "checklist_item_id": "slide-13.composition", + "expected_failed_item_ids": [ + "slide-13.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.composition", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-decorative-detail", + "checklist_item_id": "slide-13.decorative-detail", + "expected_failed_item_ids": [ + "slide-13.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.decorative-detail", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-focal-fidelity", + "checklist_item_id": "slide-13.focal-fidelity", + "expected_failed_item_ids": [ + "slide-13.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-font-policy", + "checklist_item_id": "slide-13.font-policy", + "expected_failed_item_ids": [ + "slide-13.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-full-slide-fidelity", + "checklist_item_id": "slide-13.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-13.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-hierarchy-z-order", + "checklist_item_id": "slide-13.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-13.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-key-text", + "checklist_item_id": "slide-13.key-text", + "expected_failed_item_ids": [ + "slide-13.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-layout-binding", + "checklist_item_id": "slide-13.layout-binding", + "expected_failed_item_ids": [ + "slide-13.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-native-primary", + "checklist_item_id": "slide-13.native-primary", + "expected_failed_item_ids": [ + "slide-13.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-palette", + "checklist_item_id": "slide-13.palette", + "expected_failed_item_ids": [ + "slide-13.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-semantic-structure", + "checklist_item_id": "slide-13.semantic-structure", + "expected_failed_item_ids": [ + "slide-13.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-spacing", + "checklist_item_id": "slide-13.spacing", + "expected_failed_item_ids": [ + "slide-13.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-13.assert-typography", + "checklist_item_id": "slide-13.typography", + "expected_failed_item_ids": [ + "slide-13.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-13.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-composition", + "checklist_item_id": "slide-14.composition", + "expected_failed_item_ids": [ + "slide-14.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-decorative-detail", + "checklist_item_id": "slide-14.decorative-detail", + "expected_failed_item_ids": [ + "slide-14.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-focal-fidelity", + "checklist_item_id": "slide-14.focal-fidelity", + "expected_failed_item_ids": [ + "slide-14.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-font-policy", + "checklist_item_id": "slide-14.font-policy", + "expected_failed_item_ids": [ + "slide-14.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-full-slide-fidelity", + "checklist_item_id": "slide-14.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-14.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-hierarchy-z-order", + "checklist_item_id": "slide-14.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-14.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-key-text", + "checklist_item_id": "slide-14.key-text", + "expected_failed_item_ids": [ + "slide-14.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-layout-binding", + "checklist_item_id": "slide-14.layout-binding", + "expected_failed_item_ids": [ + "slide-14.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-native-primary", + "checklist_item_id": "slide-14.native-primary", + "expected_failed_item_ids": [ + "slide-14.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-palette", + "checklist_item_id": "slide-14.palette", + "expected_failed_item_ids": [ + "slide-14.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-semantic-structure", + "checklist_item_id": "slide-14.semantic-structure", + "expected_failed_item_ids": [ + "slide-14.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-spacing", + "checklist_item_id": "slide-14.spacing", + "expected_failed_item_ids": [ + "slide-14.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-14.assert-typography", + "checklist_item_id": "slide-14.typography", + "expected_failed_item_ids": [ + "slide-14.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-14.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-composition", + "checklist_item_id": "slide-15.composition", + "expected_failed_item_ids": [ + "slide-15.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-decorative-detail", + "checklist_item_id": "slide-15.decorative-detail", + "expected_failed_item_ids": [ + "slide-15.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-focal-fidelity", + "checklist_item_id": "slide-15.focal-fidelity", + "expected_failed_item_ids": [ + "slide-15.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-font-policy", + "checklist_item_id": "slide-15.font-policy", + "expected_failed_item_ids": [ + "slide-15.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-full-slide-fidelity", + "checklist_item_id": "slide-15.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-15.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-hierarchy-z-order", + "checklist_item_id": "slide-15.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-15.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-key-text", + "checklist_item_id": "slide-15.key-text", + "expected_failed_item_ids": [ + "slide-15.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-layout-binding", + "checklist_item_id": "slide-15.layout-binding", + "expected_failed_item_ids": [ + "slide-15.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-native-primary", + "checklist_item_id": "slide-15.native-primary", + "expected_failed_item_ids": [ + "slide-15.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-palette", + "checklist_item_id": "slide-15.palette", + "expected_failed_item_ids": [ + "slide-15.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-semantic-structure", + "checklist_item_id": "slide-15.semantic-structure", + "expected_failed_item_ids": [ + "slide-15.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-spacing", + "checklist_item_id": "slide-15.spacing", + "expected_failed_item_ids": [ + "slide-15.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-15.assert-typography", + "checklist_item_id": "slide-15.typography", + "expected_failed_item_ids": [ + "slide-15.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-15.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-composition", + "checklist_item_id": "slide-16.composition", + "expected_failed_item_ids": [ + "slide-16.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-decorative-detail", + "checklist_item_id": "slide-16.decorative-detail", + "expected_failed_item_ids": [ + "slide-16.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-focal-fidelity", + "checklist_item_id": "slide-16.focal-fidelity", + "expected_failed_item_ids": [ + "slide-16.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-font-policy", + "checklist_item_id": "slide-16.font-policy", + "expected_failed_item_ids": [ + "slide-16.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-full-slide-fidelity", + "checklist_item_id": "slide-16.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-16.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-hierarchy-z-order", + "checklist_item_id": "slide-16.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-16.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-key-text", + "checklist_item_id": "slide-16.key-text", + "expected_failed_item_ids": [ + "slide-16.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-layout-binding", + "checklist_item_id": "slide-16.layout-binding", + "expected_failed_item_ids": [ + "slide-16.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-native-primary", + "checklist_item_id": "slide-16.native-primary", + "expected_failed_item_ids": [ + "slide-16.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-palette", + "checklist_item_id": "slide-16.palette", + "expected_failed_item_ids": [ + "slide-16.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-semantic-structure", + "checklist_item_id": "slide-16.semantic-structure", + "expected_failed_item_ids": [ + "slide-16.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-spacing", + "checklist_item_id": "slide-16.spacing", + "expected_failed_item_ids": [ + "slide-16.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-16.assert-typography", + "checklist_item_id": "slide-16.typography", + "expected_failed_item_ids": [ + "slide-16.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-16.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-composition", + "checklist_item_id": "slide-17.composition", + "expected_failed_item_ids": [ + "slide-17.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-decorative-detail", + "checklist_item_id": "slide-17.decorative-detail", + "expected_failed_item_ids": [ + "slide-17.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-focal-fidelity", + "checklist_item_id": "slide-17.focal-fidelity", + "expected_failed_item_ids": [ + "slide-17.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-font-policy", + "checklist_item_id": "slide-17.font-policy", + "expected_failed_item_ids": [ + "slide-17.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-full-slide-fidelity", + "checklist_item_id": "slide-17.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-17.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-hierarchy-z-order", + "checklist_item_id": "slide-17.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-17.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-key-text", + "checklist_item_id": "slide-17.key-text", + "expected_failed_item_ids": [ + "slide-17.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-layout-binding", + "checklist_item_id": "slide-17.layout-binding", + "expected_failed_item_ids": [ + "slide-17.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-native-primary", + "checklist_item_id": "slide-17.native-primary", + "expected_failed_item_ids": [ + "slide-17.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.native-primary", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-palette", + "checklist_item_id": "slide-17.palette", + "expected_failed_item_ids": [ + "slide-17.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-semantic-structure", + "checklist_item_id": "slide-17.semantic-structure", + "expected_failed_item_ids": [ + "slide-17.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.semantic-structure", + "mutation_operator": "decrement-group-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-spacing", + "checklist_item_id": "slide-17.spacing", + "expected_failed_item_ids": [ + "slide-17.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-17.assert-typography", + "checklist_item_id": "slide-17.typography", + "expected_failed_item_ids": [ + "slide-17.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-17.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-composition", + "checklist_item_id": "slide-18.composition", + "expected_failed_item_ids": [ + "slide-18.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-decorative-detail", + "checklist_item_id": "slide-18.decorative-detail", + "expected_failed_item_ids": [ + "slide-18.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-focal-fidelity", + "checklist_item_id": "slide-18.focal-fidelity", + "expected_failed_item_ids": [ + "slide-18.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-font-policy", + "checklist_item_id": "slide-18.font-policy", + "expected_failed_item_ids": [ + "slide-18.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-full-slide-fidelity", + "checklist_item_id": "slide-18.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-18.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-hierarchy-z-order", + "checklist_item_id": "slide-18.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-18.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-key-text", + "checklist_item_id": "slide-18.key-text", + "expected_failed_item_ids": [ + "slide-18.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-layout-binding", + "checklist_item_id": "slide-18.layout-binding", + "expected_failed_item_ids": [ + "slide-18.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-native-primary", + "checklist_item_id": "slide-18.native-primary", + "expected_failed_item_ids": [ + "slide-18.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.native-primary", + "mutation_operator": "replace-approved-asset-hash", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-palette", + "checklist_item_id": "slide-18.palette", + "expected_failed_item_ids": [ + "slide-18.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-semantic-structure", + "checklist_item_id": "slide-18.semantic-structure", + "expected_failed_item_ids": [ + "slide-18.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.semantic-structure", + "mutation_operator": "decrement-picture-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-spacing", + "checklist_item_id": "slide-18.spacing", + "expected_failed_item_ids": [ + "slide-18.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-18.assert-typography", + "checklist_item_id": "slide-18.typography", + "expected_failed_item_ids": [ + "slide-18.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-18.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-composition", + "checklist_item_id": "slide-19.composition", + "expected_failed_item_ids": [ + "slide-19.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.composition", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-decorative-detail", + "checklist_item_id": "slide-19.decorative-detail", + "expected_failed_item_ids": [ + "slide-19.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.decorative-detail", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-focal-fidelity", + "checklist_item_id": "slide-19.focal-fidelity", + "expected_failed_item_ids": [ + "slide-19.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-font-policy", + "checklist_item_id": "slide-19.font-policy", + "expected_failed_item_ids": [ + "slide-19.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-full-slide-fidelity", + "checklist_item_id": "slide-19.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-19.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-hierarchy-z-order", + "checklist_item_id": "slide-19.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-19.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.hierarchy-z-order", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-key-text", + "checklist_item_id": "slide-19.key-text", + "expected_failed_item_ids": [ + "slide-19.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-layout-binding", + "checklist_item_id": "slide-19.layout-binding", + "expected_failed_item_ids": [ + "slide-19.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.layout-binding", + "mutation_operator": "remove-required-placeholder", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-native-primary", + "checklist_item_id": "slide-19.native-primary", + "expected_failed_item_ids": [ + "slide-19.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.native-primary", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-palette", + "checklist_item_id": "slide-19.palette", + "expected_failed_item_ids": [ + "slide-19.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-semantic-structure", + "checklist_item_id": "slide-19.semantic-structure", + "expected_failed_item_ids": [ + "slide-19.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.semantic-structure", + "mutation_operator": "decrement-shape-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-spacing", + "checklist_item_id": "slide-19.spacing", + "expected_failed_item_ids": [ + "slide-19.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-19.assert-typography", + "checklist_item_id": "slide-19.typography", + "expected_failed_item_ids": [ + "slide-19.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-19.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-composition", + "checklist_item_id": "slide-20.composition", + "expected_failed_item_ids": [ + "slide-20.composition" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.composition", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-decorative-detail", + "checklist_item_id": "slide-20.decorative-detail", + "expected_failed_item_ids": [ + "slide-20.decorative-detail" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.decorative-detail", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-focal-fidelity", + "checklist_item_id": "slide-20.focal-fidelity", + "expected_failed_item_ids": [ + "slide-20.focal-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.focal-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-font-policy", + "checklist_item_id": "slide-20.font-policy", + "expected_failed_item_ids": [ + "slide-20.font-policy" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.font-policy", + "mutation_operator": "substitute-non-bundled-font", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-full-slide-fidelity", + "checklist_item_id": "slide-20.full-slide-fidelity", + "expected_failed_item_ids": [ + "slide-20.full-slide-fidelity" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.full-slide-fidelity", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-hierarchy-z-order", + "checklist_item_id": "slide-20.hierarchy-z-order", + "expected_failed_item_ids": [ + "slide-20.hierarchy-z-order" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.hierarchy-z-order", + "mutation_operator": "decrement-table-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-key-text", + "checklist_item_id": "slide-20.key-text", + "expected_failed_item_ids": [ + "slide-20.key-text" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.key-text", + "mutation_operator": "replace-required-text", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-layout-binding", + "checklist_item_id": "slide-20.layout-binding", + "expected_failed_item_ids": [ + "slide-20.layout-binding" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.layout-binding", + "mutation_operator": "clear-layout-reference", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-native-primary", + "checklist_item_id": "slide-20.native-primary", + "expected_failed_item_ids": [ + "slide-20.native-primary" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.native-primary", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-palette", + "checklist_item_id": "slide-20.palette", + "expected_failed_item_ids": [ + "slide-20.palette" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.palette", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-semantic-structure", + "checklist_item_id": "slide-20.semantic-structure", + "expected_failed_item_ids": [ + "slide-20.semantic-structure" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.semantic-structure", + "mutation_operator": "decrement-chart-count", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-spacing", + "checklist_item_id": "slide-20.spacing", + "expected_failed_item_ids": [ + "slide-20.spacing" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.spacing", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + }, + { + "assertion_id": "slide-20.assert-typography", + "checklist_item_id": "slide-20.typography", + "expected_failed_item_ids": [ + "slide-20.typography" + ], + "fault_count": 1, + "mutation_expectation_id": "mutation.slide-20.typography", + "mutation_operator": "lower-ssim-below-threshold", + "negative_expected_outcome": "failed", + "positive_expected_outcome": "passed", + "release_evidence_claimed": false + } + ], + "fixture_index_id": "acidslide-generated-mutation-fixture-index-v1", + "schema_version": "1.0", + "summary": { + "expectations": 280, + "single_fault_expectations": 280, + "unimplemented": 0 + }, + "unresolved": [] +} diff --git a/acidslide-v1/benchmark/fixtures/package-hash/gold-copy-rejection-v1.json b/acidslide-v1/benchmark/fixtures/package-hash/gold-copy-rejection-v1.json new file mode 100644 index 0000000..73ad34d --- /dev/null +++ b/acidslide-v1/benchmark/fixtures/package-hash/gold-copy-rejection-v1.json @@ -0,0 +1,41 @@ +{ + "schema_version": "1.0", + "fixture_id": "synthetic-gold-copy-rejection-v1", + "gold_parts": { + "[Content_Types].xml": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48VHlwZXMgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9wYWNrYWdlLzIwMDYvY29udGVudC10eXBlcyI+PERlZmF1bHQgRXh0ZW5zaW9uPSJyZWxzIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLXBhY2thZ2UucmVsYXRpb25zaGlwcyt4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii9kb2NQcm9wcy9jb3JlLnhtbCIgQ29udGVudFR5cGU9ImFwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1wYWNrYWdlLmNvcmUtcHJvcGVydGllcyt4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii9wcHQvcHJlc2VudGF0aW9uLnhtbCIgQ29udGVudFR5cGU9ImFwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC5wcmVzZW50YXRpb25tbC5wcmVzZW50YXRpb24ubWFpbit4bWwiLz48L1R5cGVzPg==", + "_rels/.rels": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48UmVsYXRpb25zaGlwcyB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3BhY2thZ2UvMjAwNi9yZWxhdGlvbnNoaXBzIj48UmVsYXRpb25zaGlwIElkPSJySWQyIiBUeXBlPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvcGFja2FnZS8yMDA2L3JlbGF0aW9uc2hpcHMvbWV0YWRhdGEvY29yZS1wcm9wZXJ0aWVzIiBUYXJnZXQ9ImRvY1Byb3BzL2NvcmUueG1sIi8+PFJlbGF0aW9uc2hpcCBJZD0icklkMSIgVHlwZT0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL29mZmljZURvY3VtZW50LzIwMDYvcmVsYXRpb25zaGlwcy9vZmZpY2VEb2N1bWVudCIgVGFyZ2V0PSJwcHQvcHJlc2VudGF0aW9uLnhtbCIvPjwvUmVsYXRpb25zaGlwcz4=", + "docProps/core.xml": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y3A6Y29yZVByb3BlcnRpZXMgeG1sbnM6Y3A9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9wYWNrYWdlLzIwMDYvbWV0YWRhdGEvY29yZS1wcm9wZXJ0aWVzIiB4bWxuczpkY3Rlcm1zPSJodHRwOi8vcHVybC5vcmcvZGMvdGVybXMvIj48ZGN0ZXJtczpjcmVhdGVkPjIwMjYtMDctMThUMDA6MDA6MDBaPC9kY3Rlcm1zOmNyZWF0ZWQ+PGNwOnJldmlzaW9uPjE8L2NwOnJldmlzaW9uPjwvY3A6Y29yZVByb3BlcnRpZXM+", + "ppt/presentation.xml": "PHA6cHJlc2VudGF0aW9uIHhtbG5zOnA9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9wcmVzZW50YXRpb25tbC8yMDA2L21haW4iPjxwOnNsZElkTHN0Lz48L3A6cHJlc2VudGF0aW9uPg==" + }, + "cases": [ + { + "id": "exact-gold-bytes", + "recipe": "exact_bytes", + "expect_byte_match": true, + "expect_package_match": true, + "expected_decision": "gold_artifact_copy" + }, + { + "id": "repacked-gold", + "recipe": "repacked", + "expect_byte_match": false, + "expect_package_match": true, + "expected_decision": "gold_artifact_copy" + }, + { + "id": "volatile-metadata-only", + "recipe": "volatile_core_changed", + "expect_byte_match": false, + "expect_package_match": true, + "expected_decision": "gold_artifact_copy" + }, + { + "id": "nonvolatile-content-change", + "recipe": "content_changed", + "expect_byte_match": false, + "expect_package_match": false, + "expected_decision": "not_a_gold_copy" + } + ], + "expected_canonical_sha256": "2af1ca72d58ae9e851048966c54cfcf49fbee5f0f08e487b75af0ae980a6ad23" +} diff --git a/acidslide-v1/benchmark/fonts/LICENSE b/acidslide-v1/benchmark/fonts/LICENSE new file mode 100644 index 0000000..ec78af7 --- /dev/null +++ b/acidslide-v1/benchmark/fonts/LICENSE @@ -0,0 +1,20 @@ +AcidSlide v1 Bundled Font Licensing + +The files under `files/` are unmodified copies extracted from the exact Ubuntu +22.04 packages listed in `manifest.json`. They are redistributable under the +following licenses: + +- Liberation Sans, Serif, and Mono 1.07.4: GPL-2.0 with the font embedding + exception. See `licenses/fonts-liberation-1.07.4-11.txt`. +- Carlito: SIL Open Font License 1.1. The Reserved Font Name is "Carlito". + See `licenses/fonts-crosextra-carlito-20130920-1.1.txt`. +- Caladea: Apache License 2.0. + See `licenses/fonts-crosextra-caladea-20130214-2.1.txt`. +- Noto Sans and Noto Sans Arabic: SIL Open Font License 1.1. + See `licenses/fonts-noto-core-20201225-1build1.txt`. +- Noto Sans CJK: SIL Open Font License 1.1. + See `licenses/fonts-noto-cjk-20220127+repack1-1.txt`. + +The package URLs, exact package versions, package hashes, individual file +hashes, family names, and styles are recorded in `manifest.json`. No commercial +or operating-system-proprietary font is included. diff --git a/acidslide-v1/benchmark/fonts/files/Caladea-Bold.ttf b/acidslide-v1/benchmark/fonts/files/Caladea-Bold.ttf new file mode 100644 index 0000000..a41e29a Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Caladea-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Caladea-BoldItalic.ttf b/acidslide-v1/benchmark/fonts/files/Caladea-BoldItalic.ttf new file mode 100644 index 0000000..ea72b2e Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Caladea-BoldItalic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Caladea-Italic.ttf b/acidslide-v1/benchmark/fonts/files/Caladea-Italic.ttf new file mode 100644 index 0000000..055a68f Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Caladea-Italic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Caladea-Regular.ttf b/acidslide-v1/benchmark/fonts/files/Caladea-Regular.ttf new file mode 100644 index 0000000..a080253 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Caladea-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Carlito-Bold.ttf b/acidslide-v1/benchmark/fonts/files/Carlito-Bold.ttf new file mode 100644 index 0000000..b29a590 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Carlito-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Carlito-BoldItalic.ttf b/acidslide-v1/benchmark/fonts/files/Carlito-BoldItalic.ttf new file mode 100644 index 0000000..0eaa04e Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Carlito-BoldItalic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Carlito-Italic.ttf b/acidslide-v1/benchmark/fonts/files/Carlito-Italic.ttf new file mode 100644 index 0000000..64df01e Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Carlito-Italic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/Carlito-Regular.ttf b/acidslide-v1/benchmark/fonts/files/Carlito-Regular.ttf new file mode 100644 index 0000000..6b7e0e3 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/Carlito-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationMono-Bold.ttf b/acidslide-v1/benchmark/fonts/files/LiberationMono-Bold.ttf new file mode 100644 index 0000000..21ec83f Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationMono-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationMono-BoldItalic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationMono-BoldItalic.ttf new file mode 100644 index 0000000..91c00bb Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationMono-BoldItalic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationMono-Italic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationMono-Italic.ttf new file mode 100644 index 0000000..24fc9b1 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationMono-Italic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationMono-Regular.ttf b/acidslide-v1/benchmark/fonts/files/LiberationMono-Regular.ttf new file mode 100644 index 0000000..64b0f70 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationMono-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSans-Bold.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSans-Bold.ttf new file mode 100644 index 0000000..52edeb2 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSans-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSans-BoldItalic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSans-BoldItalic.ttf new file mode 100644 index 0000000..541f409 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSans-BoldItalic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSans-Italic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSans-Italic.ttf new file mode 100644 index 0000000..d83f505 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSans-Italic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSans-Regular.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSans-Regular.ttf new file mode 100644 index 0000000..cc01210 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSans-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSerif-Bold.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Bold.ttf new file mode 100644 index 0000000..818d87e Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSerif-BoldItalic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSerif-BoldItalic.ttf new file mode 100644 index 0000000..02f22dd Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSerif-BoldItalic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSerif-Italic.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Italic.ttf new file mode 100644 index 0000000..84cdceb Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Italic.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/LiberationSerif-Regular.ttf b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Regular.ttf new file mode 100644 index 0000000..4786d50 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/LiberationSerif-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSans-Bold.ttf b/acidslide-v1/benchmark/fonts/files/NotoSans-Bold.ttf new file mode 100644 index 0000000..4d923cb Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSans-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSans-Regular.ttf b/acidslide-v1/benchmark/fonts/files/NotoSans-Regular.ttf new file mode 100644 index 0000000..7e9c169 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSans-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Bold.ttf b/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Bold.ttf new file mode 100644 index 0000000..98d9cdb Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Bold.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Regular.ttf b/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Regular.ttf new file mode 100644 index 0000000..a3c66dc Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSansArabic-Regular.ttf differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Bold.ttc b/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Bold.ttc new file mode 100644 index 0000000..ce48b99 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Bold.ttc differ diff --git a/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Regular.ttc b/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Regular.ttc new file mode 100644 index 0000000..a2033d0 Binary files /dev/null and b/acidslide-v1/benchmark/fonts/files/NotoSansCJK-Regular.ttc differ diff --git a/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-caladea-20130214-2.1.txt b/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-caladea-20130214-2.1.txt new file mode 100644 index 0000000..93c5c43 --- /dev/null +++ b/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-caladea-20130214-2.1.txt @@ -0,0 +1,30 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: crosextrafonts +Source: http://gsdview.appspot.com/chromeos-localmirror/distfiles/ +Comment: + License added in font as "otfinfo -i Caladea-Regular.ttf | grep License" + also from https://bugs.chromium.org/p/chromium/issues/detail?id=280557 + +Files: * +Copyright: 2012, Huerta Tipografia +License: Apache-2.0 + +Files: debian/* +Copyright: 2014-2017, Fabian Greffrath +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-carlito-20130920-1.1.txt b/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-carlito-20130920-1.1.txt new file mode 100644 index 0000000..e1ca37c --- /dev/null +++ b/acidslide-v1/benchmark/fonts/licenses/fonts-crosextra-carlito-20130920-1.1.txt @@ -0,0 +1,121 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: crosextrafonts-carlito +Source: http://gsdview.appspot.com/chromeos-localmirror/distfiles/ + +Files: * +Copyright: 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Carlito". +License: OFL-1.1 + Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Carlito". + . + This Font Software is licensed under the SIL Open Font License, + Version 1.1 as shown below. + . + SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + . + PREAMBLE The goals of the Open Font License (OFL) are to stimulate + worldwide development of collaborative font projects, to support the font + creation efforts of academic and linguistic communities, and to provide + a free and open framework in which fonts may be shared and improved in + partnership with others. + . + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. + The fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply to + any document created using the fonts or their derivatives. + . + . + DEFINITIONS + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. + This may include source files, build scripts and documentation. + . + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + . + "Original Version" refers to the collection of Font Software components + as distributed by the Copyright Holder(s). + . + "Modified Version" refers to any derivative made by adding to, deleting, + or substituting ? in part or in whole ? + any of the components of the Original Version, by changing formats or + by porting the Font Software to a new environment. + . + "Author" refers to any designer, engineer, programmer, technical writer + or other person who contributed to the Font Software. + . + . + PERMISSION & CONDITIONS + . + Permission is hereby granted, free of charge, to any person obtaining a + copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + . + 1) Neither the Font Software nor any of its individual components,in + Original or Modified Versions, may be sold by itself. + . + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + . + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + . + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + . + 5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under + this license does not apply to any document created using the Font + Software. + . + . + . + TERMINATION + This license becomes null and void if any of the above conditions are not met. + . + . + . + DISCLAIMER + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER + DEALINGS IN THE FONT SOFTWARE. + . + +Files: debian/* +Copyright: 2014, Fabian Greffrath +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". diff --git a/acidslide-v1/benchmark/fonts/licenses/fonts-liberation-1.07.4-11.txt b/acidslide-v1/benchmark/fonts/licenses/fonts-liberation-1.07.4-11.txt new file mode 100644 index 0000000..3265615 --- /dev/null +++ b/acidslide-v1/benchmark/fonts/licenses/fonts-liberation-1.07.4-11.txt @@ -0,0 +1,73 @@ +This package was debianized by Alan Baghumian on +Sat, 12 May 2007 16:13:31 +0330. + +It was downloaded from https://pagure.io/liberation-fonts/ + +Upstream Author: Red Hat Inc. + +Copyright: (C) 2007 Red Hat, Inc. All rights reserved. + LIBERATION is a trademark of Red Hat, Inc. + +License: + + This agreement governs the use of the Software and any updates to the Software, + regardless of the delivery mechanism. Subject to the following terms, Red Hat, Inc. + ("Red Hat") grants to the user ("Client") a license to this work pursuant to + the GNU General Public License v.2 with the exceptions set forth below and such + other terms as our set forth in this End User License Agreement. + + 1. The Software and License Exception. LIBERATION font software (the "Software") + consists of TrueType-OpenType formatted font software for rendering LIBERATION + typefaces in sans serif, serif, and monospaced character styles. You are licensed + to use, modify, copy, and distribute the Software pursuant to the GNU General + Public License v.2 with the following exceptions: + + (a) As a special exception, if you create a document which uses this font, and + embed this font or unaltered portions of this font into the document, this + font does not by itself cause the resulting document to be covered by the + GNU General Public License.  This exception does not however invalidate any + other reasons why the document might be covered by the GNU General Public + License.  If you modify this font, you may extend this exception to your + version of the font, but you are not obligated to do so. If you do not + wish to do so, delete this exception statement from your version. + + (b) As a further exception, any distribution of the object code of the Software + in a physical product must provide you the right to access and modify the + source code for the Software and to reinstall that modified version of the + Software in object code form on the same physical product on which you + received it. + + 2. Intellectual Property Rights. The Software and each of its components, including + the source code, documentation, appearance, structure and organization are owned + by Red Hat and others and are protected under copyright and other laws. Title to + the Software and any component, or to any copy, modification, or merged portion + shall remain with the aforementioned, subject to the applicable license. + The "LIBERATION" trademark is a trademark of Red Hat, Inc. in the U.S. and other + countries. This agreement does not permit Client to distribute modified versions + of the Software using Red Hat's trademarks. If Client makes a redistribution of + a modified version of the Software, then Client must modify the files names to + remove any reference to the Red Hat trademarks and must not use the Red Hat + trademarks in any way to reference or promote the modified Software. + + 3. Limited Warranty. To the maximum extent permitted under applicable law, the + Software is provided and licensed "as is" without warranty of any kind, + expressed or implied, including the implied warranties of merchantability, + non-infringement or fitness for a particular purpose. Red Hat does not warrant + that the functions contained in the Software will meet Client's requirements or + that the operation of the Software will be entirely error free or appear precisely + as described in the accompanying documentation. + + 4. Limitation of Remedies and Liability. To the maximum extent permitted by applicable + law, Red Hat or any Red Hat authorized dealer will not be liable to Client for any + incidental or consequential damages, including lost profits or lost savings arising + out of the use or inability to use the Software, even if Red Hat or such dealer has + been advised of the possibility of such damages. + + 5. General. If any provision of this agreement is held to be unenforceable, that shall + not affect the enforceability of the remaining provisions. This agreement shall be + governed by the laws of the State of North Carolina and of the United States, without + regard to any conflict of laws provisions, except that the United Nations Convention + on the International Sale of Goods shall not apply. + +On Debian systems, the complete text of the GNU General +Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'. diff --git a/acidslide-v1/benchmark/fonts/licenses/fonts-noto-cjk-20220127+repack1-1.txt b/acidslide-v1/benchmark/fonts/licenses/fonts-noto-cjk-20220127+repack1-1.txt new file mode 100644 index 0000000..f5b058a --- /dev/null +++ b/acidslide-v1/benchmark/fonts/licenses/fonts-noto-cjk-20220127+repack1-1.txt @@ -0,0 +1,327 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: noto-cjk +Upstream-Contact: https://github.com/googlefonts/noto-cjk/issues +Source: https://github.com/googlefonts/noto-cjk +Files-Excluded: + .gitattributes + .gitignore + Sans/Mono/NotoSansMonoCJKhk-Bold.otf + Sans/Mono/NotoSansMonoCJKhk-Regular.otf + Sans/Mono/NotoSansMonoCJKjp-Bold.otf + Sans/Mono/NotoSansMonoCJKjp-Regular.otf + Sans/Mono/NotoSansMonoCJKkr-Bold.otf + Sans/Mono/NotoSansMonoCJKkr-Regular.otf + Sans/Mono/NotoSansMonoCJKsc-Bold.otf + Sans/Mono/NotoSansMonoCJKsc-Regular.otf + Sans/Mono/NotoSansMonoCJKtc-Bold.otf + Sans/Mono/NotoSansMonoCJKtc-Regular.otf + Sans/OTF/Japanese/NotoSansCJKjp-Black.otf + Sans/OTF/Japanese/NotoSansCJKjp-Bold.otf + Sans/OTF/Japanese/NotoSansCJKjp-DemiLight.otf + Sans/OTF/Japanese/NotoSansCJKjp-Light.otf + Sans/OTF/Japanese/NotoSansCJKjp-Medium.otf + Sans/OTF/Japanese/NotoSansCJKjp-Regular.otf + Sans/OTF/Japanese/NotoSansCJKjp-Thin.otf + Sans/OTF/Korean/NotoSansCJKkr-Black.otf + Sans/OTF/Korean/NotoSansCJKkr-Bold.otf + Sans/OTF/Korean/NotoSansCJKkr-DemiLight.otf + Sans/OTF/Korean/NotoSansCJKkr-Light.otf + Sans/OTF/Korean/NotoSansCJKkr-Medium.otf + Sans/OTF/Korean/NotoSansCJKkr-Regular.otf + Sans/OTF/Korean/NotoSansCJKkr-Thin.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Black.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Bold.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-DemiLight.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Light.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Medium.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Regular.otf + Sans/OTF/SimplifiedChinese/NotoSansCJKsc-Thin.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Black.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Bold.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-DemiLight.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Light.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Medium.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Regular.otf + Sans/OTF/TraditionalChinese/NotoSansCJKtc-Thin.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Black.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Bold.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-DemiLight.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Light.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Medium.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Regular.otf + Sans/OTF/TraditionalChineseHK/NotoSansCJKhk-Thin.otf + Sans/SubsetOTF/HK/NotoSansHK-Black.otf + Sans/SubsetOTF/HK/NotoSansHK-Bold.otf + Sans/SubsetOTF/HK/NotoSansHK-DemiLight.otf + Sans/SubsetOTF/HK/NotoSansHK-Light.otf + Sans/SubsetOTF/HK/NotoSansHK-Medium.otf + Sans/SubsetOTF/HK/NotoSansHK-Regular.otf + Sans/SubsetOTF/HK/NotoSansHK-Thin.otf + Sans/SubsetOTF/JP/NotoSansJP-Black.otf + Sans/SubsetOTF/JP/NotoSansJP-Bold.otf + Sans/SubsetOTF/JP/NotoSansJP-DemiLight.otf + Sans/SubsetOTF/JP/NotoSansJP-Light.otf + Sans/SubsetOTF/JP/NotoSansJP-Medium.otf + Sans/SubsetOTF/JP/NotoSansJP-Regular.otf + Sans/SubsetOTF/JP/NotoSansJP-Thin.otf + Sans/SubsetOTF/KR/NotoSansKR-Black.otf + Sans/SubsetOTF/KR/NotoSansKR-Bold.otf + Sans/SubsetOTF/KR/NotoSansKR-DemiLight.otf + Sans/SubsetOTF/KR/NotoSansKR-Light.otf + Sans/SubsetOTF/KR/NotoSansKR-Medium.otf + Sans/SubsetOTF/KR/NotoSansKR-Regular.otf + Sans/SubsetOTF/KR/NotoSansKR-Thin.otf + Sans/SubsetOTF/SC/NotoSansSC-Black.otf + Sans/SubsetOTF/SC/NotoSansSC-Bold.otf + Sans/SubsetOTF/SC/NotoSansSC-DemiLight.otf + Sans/SubsetOTF/SC/NotoSansSC-Light.otf + Sans/SubsetOTF/SC/NotoSansSC-Medium.otf + Sans/SubsetOTF/SC/NotoSansSC-Regular.otf + Sans/SubsetOTF/SC/NotoSansSC-Thin.otf + Sans/SubsetOTF/TC/NotoSansTC-Black.otf + Sans/SubsetOTF/TC/NotoSansTC-Bold.otf + Sans/SubsetOTF/TC/NotoSansTC-DemiLight.otf + Sans/SubsetOTF/TC/NotoSansTC-Light.otf + Sans/SubsetOTF/TC/NotoSansTC-Medium.otf + Sans/SubsetOTF/TC/NotoSansTC-Regular.otf + Sans/SubsetOTF/TC/NotoSansTC-Thin.otf + Sans/SuperOTC/NotoSansCJK.ttc.zip + Sans/Variable/OTC/NotoSansCJK-VF.ttf.ttc + Sans/Variable/OTC/NotoSansMonoCJK-VF.ttf.ttc + Sans/Variable/OTF/Mono/NotoSansMonoCJKhk-VF.otf + Sans/Variable/OTF/Mono/NotoSansMonoCJKjp-VF.otf + Sans/Variable/OTF/Mono/NotoSansMonoCJKkr-VF.otf + Sans/Variable/OTF/Mono/NotoSansMonoCJKsc-VF.otf + Sans/Variable/OTF/Mono/NotoSansMonoCJKtc-VF.otf + Sans/Variable/OTF/NotoSansCJKhk-VF.otf + Sans/Variable/OTF/NotoSansCJKjp-VF.otf + Sans/Variable/OTF/NotoSansCJKkr-VF.otf + Sans/Variable/OTF/NotoSansCJKsc-VF.otf + Sans/Variable/OTF/NotoSansCJKtc-VF.otf + Sans/Variable/OTF/Subset/NotoSansHK-VF.otf + Sans/Variable/OTF/Subset/NotoSansJP-VF.otf + Sans/Variable/OTF/Subset/NotoSansKR-VF.otf + Sans/Variable/OTF/Subset/NotoSansSC-VF.otf + Sans/Variable/OTF/Subset/NotoSansTC-VF.otf + Sans/Variable/TTF/Mono/NotoSansMonoCJKhk-VF.ttf + Sans/Variable/TTF/Mono/NotoSansMonoCJKjp-VF.ttf + Sans/Variable/TTF/Mono/NotoSansMonoCJKkr-VF.ttf + Sans/Variable/TTF/Mono/NotoSansMonoCJKsc-VF.ttf + Sans/Variable/TTF/Mono/NotoSansMonoCJKtc-VF.ttf + Sans/Variable/TTF/NotoSansCJKhk-VF.ttf + Sans/Variable/TTF/NotoSansCJKjp-VF.ttf + Sans/Variable/TTF/NotoSansCJKkr-VF.ttf + Sans/Variable/TTF/NotoSansCJKsc-VF.ttf + Sans/Variable/TTF/NotoSansCJKtc-VF.ttf + Sans/Variable/TTF/Subset/NotoSansHK-VF.ttf + Sans/Variable/TTF/Subset/NotoSansJP-VF.ttf + Sans/Variable/TTF/Subset/NotoSansKR-VF.ttf + Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf + Sans/Variable/TTF/Subset/NotoSansTC-VF.ttf + Serif/OTF/Japanese/NotoSerifCJKjp-Black.otf + Serif/OTF/Japanese/NotoSerifCJKjp-Bold.otf + Serif/OTF/Japanese/NotoSerifCJKjp-ExtraLight.otf + Serif/OTF/Japanese/NotoSerifCJKjp-Light.otf + Serif/OTF/Japanese/NotoSerifCJKjp-Medium.otf + Serif/OTF/Japanese/NotoSerifCJKjp-Regular.otf + Serif/OTF/Japanese/NotoSerifCJKjp-SemiBold.otf + Serif/OTF/Korean/NotoSerifCJKkr-Black.otf + Serif/OTF/Korean/NotoSerifCJKkr-Bold.otf + Serif/OTF/Korean/NotoSerifCJKkr-ExtraLight.otf + Serif/OTF/Korean/NotoSerifCJKkr-Light.otf + Serif/OTF/Korean/NotoSerifCJKkr-Medium.otf + Serif/OTF/Korean/NotoSerifCJKkr-Regular.otf + Serif/OTF/Korean/NotoSerifCJKkr-SemiBold.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-Black.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-Bold.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-ExtraLight.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-Light.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-Medium.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-Regular.otf + Serif/OTF/SimplifiedChinese/NotoSerifCJKsc-SemiBold.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-Black.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-Bold.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-ExtraLight.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-Light.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-Medium.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-Regular.otf + Serif/OTF/TraditionalChinese/NotoSerifCJKtc-SemiBold.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-Black.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-Bold.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-ExtraLight.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-Light.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-Medium.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-Regular.otf + Serif/OTF/TraditionalChineseHK/NotoSerifCJKhk-SemiBold.otf + Serif/SubsetOTF/HK/NotoSerifHK-Black.otf + Serif/SubsetOTF/HK/NotoSerifHK-Bold.otf + Serif/SubsetOTF/HK/NotoSerifHK-ExtraLight.otf + Serif/SubsetOTF/HK/NotoSerifHK-Light.otf + Serif/SubsetOTF/HK/NotoSerifHK-Medium.otf + Serif/SubsetOTF/HK/NotoSerifHK-Regular.otf + Serif/SubsetOTF/HK/NotoSerifHK-SemiBold.otf + Serif/SubsetOTF/JP/NotoSerifJP-Black.otf + Serif/SubsetOTF/JP/NotoSerifJP-Bold.otf + Serif/SubsetOTF/JP/NotoSerifJP-ExtraLight.otf + Serif/SubsetOTF/JP/NotoSerifJP-Light.otf + Serif/SubsetOTF/JP/NotoSerifJP-Medium.otf + Serif/SubsetOTF/JP/NotoSerifJP-Regular.otf + Serif/SubsetOTF/JP/NotoSerifJP-SemiBold.otf + Serif/SubsetOTF/KR/NotoSerifKR-Black.otf + Serif/SubsetOTF/KR/NotoSerifKR-Bold.otf + Serif/SubsetOTF/KR/NotoSerifKR-ExtraLight.otf + Serif/SubsetOTF/KR/NotoSerifKR-Light.otf + Serif/SubsetOTF/KR/NotoSerifKR-Medium.otf + Serif/SubsetOTF/KR/NotoSerifKR-Regular.otf + Serif/SubsetOTF/KR/NotoSerifKR-SemiBold.otf + Serif/SubsetOTF/SC/NotoSerifSC-Black.otf + Serif/SubsetOTF/SC/NotoSerifSC-Bold.otf + Serif/SubsetOTF/SC/NotoSerifSC-ExtraLight.otf + Serif/SubsetOTF/SC/NotoSerifSC-Light.otf + Serif/SubsetOTF/SC/NotoSerifSC-Medium.otf + Serif/SubsetOTF/SC/NotoSerifSC-Regular.otf + Serif/SubsetOTF/SC/NotoSerifSC-SemiBold.otf + Serif/SubsetOTF/TC/NotoSerifTC-Black.otf + Serif/SubsetOTF/TC/NotoSerifTC-Bold.otf + Serif/SubsetOTF/TC/NotoSerifTC-ExtraLight.otf + Serif/SubsetOTF/TC/NotoSerifTC-Light.otf + Serif/SubsetOTF/TC/NotoSerifTC-Medium.otf + Serif/SubsetOTF/TC/NotoSerifTC-Regular.otf + Serif/SubsetOTF/TC/NotoSerifTC-SemiBold.otf + Serif/Variable/OTC/NotoSerifCJK-VF.ttf.ttc + Serif/Variable/OTF/NotoSerifCJKhk-VF.otf + Serif/Variable/OTF/NotoSerifCJKjp-VF.otf + Serif/Variable/OTF/NotoSerifCJKkr-VF.otf + Serif/Variable/OTF/NotoSerifCJKsc-VF.otf + Serif/Variable/OTF/NotoSerifCJKtc-VF.otf + Serif/Variable/OTF/Subset/NotoSerifHK-VF.otf + Serif/Variable/OTF/Subset/NotoSerifJP-VF.otf + Serif/Variable/OTF/Subset/NotoSerifKR-VF.otf + Serif/Variable/OTF/Subset/NotoSerifSC-VF.otf + Serif/Variable/OTF/Subset/NotoSerifTC-VF.otf + Serif/Variable/TTF/NotoSerifCJKhk-VF.ttf + Serif/Variable/TTF/NotoSerifCJKjp-VF.ttf + Serif/Variable/TTF/NotoSerifCJKkr-VF.ttf + Serif/Variable/TTF/NotoSerifCJKsc-VF.ttf + Serif/Variable/TTF/NotoSerifCJKtc-VF.ttf + Serif/Variable/TTF/Subset/NotoSerifHK-VF.ttf + Serif/Variable/TTF/Subset/NotoSerifJP-VF.ttf + Serif/Variable/TTF/Subset/NotoSerifKR-VF.ttf + Serif/Variable/TTF/Subset/NotoSerifSC-VF.ttf + Serif/Variable/TTF/Subset/NotoSerifTC-VF.ttf + +Files: * +Copyright: 2010-2012, Google Corporation +License: SIL-1.1 + +Files: debian/* +Copyright: 2013, Vasudev Kamath + 2013-2015, Jonas Smedegaard + 2015-2022, ChangZhuo Chen (陳昌倬) +License: GPL-3+ + +License: SIL-1.1 + ----------------------------------------------------------- + SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + ----------------------------------------------------------- + . + PREAMBLE + . + The goals of the Open Font License (OFL) are to stimulate worldwide + development of collaborative font projects, to support the font + creation efforts of academic and linguistic communities, and to provide + a free and open framework in which fonts may be shared and improved in + partnership with others. + . + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. The + fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply to + any document created using the fonts or their derivatives. + . + DEFINITIONS + . + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. This may + include source files, build scripts and documentation. + . + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + . + "Original Version" refers to the collection of Font Software components + as distributed by the Copyright Holder(s). + . + "Modified Version" refers to any derivative made by adding to, + deleting, or substituting -- in part or in whole -- any of the + components of the Original Version, by changing formats or by porting + the Font Software to a new environment. + . + "Author" refers to any designer, engineer, programmer, technical writer + or other person who contributed to the Font Software. + . + PERMISSION & CONDITIONS + . + Permission is hereby granted, free of charge, to any person obtaining a + copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + . + 1) Neither the Font Software nor any of its individual components, in + Original or Modified Versions, may be sold by itself. + . + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + . + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + . + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + . + 5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under this + license does not apply to any document created using the Font Software. + . + TERMINATION + . + This license becomes null and void if any of the above conditions are + not met. + . + DISCLAIMER + . + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. + +License: GPL-3+ + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". diff --git a/acidslide-v1/benchmark/fonts/licenses/fonts-noto-core-20201225-1build1.txt b/acidslide-v1/benchmark/fonts/licenses/fonts-noto-core-20201225-1build1.txt new file mode 100644 index 0000000..e9dbd01 --- /dev/null +++ b/acidslide-v1/benchmark/fonts/licenses/fonts-noto-core-20201225-1build1.txt @@ -0,0 +1,155 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Noto +Upstream-Contact: https://github.com/googlei18n/noto-fonts/issues + http://groups.google.com/group/noto-font +Source: https://github.com/googlei18n/noto-fonts + +Files: * +Copyright: + 2010,2012-2020, Google Inc. + 2015-2020, Google LLC. +License-Grant: + This Font Software is licensed under the SIL Open Font License, + Version 1.1. +License: OFL-1.1 + +Files: + debian/* +Copyright: + 2013-2020, Jonas Smedegaard + 2020, Purism, SPC + 2013, Vasudev Kamath +License-Grant: + This program is free software; + you can redistribute it and/or modify it + under the terms of the GNU General Public License + as published by the Free Software Foundation; + either version 3, or (at your option) any later version. +License: GPL-3+ + +Files: + debian/NotoMono/NotoMono-Regular.ttf +Copyright: + 2007, Google Inc. +License-Grant: + This Font Software is licensed under the SIL Open Font License, + Version 1.1. +License: OFL-1.1 + +License: OFL-1.1 + PREAMBLE + . + The goals of the Open Font License (OFL) are to stimulate + worldwide development of collaborative font projects, + to support the font creation efforts + of academic and linguistic communities, + and to provide a free and open framework + in which fonts may be shared and improved + in partnership with others. + . + The OFL allows the licensed fonts to be used, studied, + modified and redistributed freely + as long as they are not sold by themselves. + The fonts, including any derivative works, + can be bundled, embedded, + redistributed and/or sold with any software + provided that any reserved names are not used + by derivative works. + The fonts and derivatives, however, + cannot be released under any other type of license. + The requirement for fonts to remain under this license + does not apply to any document + created using the fonts or their derivatives. + . + DEFINITIONS + . + "Font Software" refers to the set of files + released by the Copyright Holder(s) under this license + and clearly marked as such. + This may include source files, build scripts and documentation. + . + "Reserved Font Name" refers to any names specified as such + after the copyright statement(s). + . + "Original Version" refers to the collection + of Font Software components + as distributed by the Copyright Holder(s). + . + "Modified Version" refers to any derivative + made by adding to, deleting, or substituting -- + in part or in whole -- + any of the components of the Original Version, + by changing formats + or by porting the Font Software to a new environment. + . + "Author" refers to any designer, engineer, programmer, + technical writer or other person + who contributed to the Font Software. + . + PERMISSION & CONDITIONS + . + Permission is hereby granted, free of charge, + to any person obtaining a copy of the Font Software, + to use, study, copy, merge, embed, modify, redistribute, + and sell modified and unmodified copies of the Font Software, + subject to the following conditions: + . + 1) Neither the Font Software nor any of its individual components, + in Original or Modified Versions, + may be sold by itself. + . + 2) Original or Modified Versions of the Font Software + may be bundled, redistributed and/or sold with any software, + provided that each copy contains the above copyright notice + and this license. + These can be included either as stand-alone text files, + human-readable headers or in the appropriate + machine-readable metadata fields within text or binary files + as long as those fields can be easily viewed by the user. + . + 3) No Modified Version of the Font Software may use + the Reserved Font Name(s) + unless explicit written permission is granted + by the corresponding Copyright Holder. + This restriction only applies to the primary font name + as presented to the users. + . + 4) The name(s) of the Copyright Holder(s) + or the Author(s) of the Font Software + shall not be used to promote, + endorse or advertise any Modified Version, + except to acknowledge the contribution(s) + of the Copyright Holder(s) and the Author(s) + or with their explicit written permission. + . + 5) The Font Software, + modified or unmodified, in part or in whole, + must be distributed entirely under this license, + and must not be distributed under any other license. + The requirement for fonts to remain under this license + does not apply to any document + created using the Font Software. + . + TERMINATION + . + This license becomes null and void + if any of the above conditions are not met. + . + DISCLAIMER + . + THE FONT SOFTWARE IS PROVIDED "AS IS", + WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO + ANY WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. + IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, + INCIDENTAL, OR CONSEQUENTIAL DAMAGES, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF THE USE OR INABILITY TO USE + THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +License: GPL-3+ +License-Reference: /usr/share/common-licenses/GPL-3 diff --git a/acidslide-v1/benchmark/fonts/manifest.json b/acidslide-v1/benchmark/fonts/manifest.json new file mode 100644 index 0000000..8ea27f7 --- /dev/null +++ b/acidslide-v1/benchmark/fonts/manifest.json @@ -0,0 +1,309 @@ +{ + "schema_version": "1.0", + "runtime": "Ubuntu 22.04 (jammy)", + "policy": "only listed font files may be used in rendered text", + "packages": [ + { + "package": "fonts-liberation", + "version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-liberation/fonts-liberation_1.07.4-11_all.deb", + "package_sha256": "d359cba9c3ac8a40fb57773881e20827845e9fab1b2d6fd25cde4b7bade7d57f", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "package": "fonts-crosextra-carlito", + "version": "20130920-1.1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/universe/f/fonts-crosextra-carlito/fonts-crosextra-carlito_20130920-1.1_all.deb", + "package_sha256": "7385475cde807e1363c3361976576571870373032466c7f525d5900852b6f420", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt" + }, + { + "package": "fonts-crosextra-caladea", + "version": "20130214-2.1", + "license": "Apache-2.0", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/universe/f/fonts-crosextra-caladea/fonts-crosextra-caladea_20130214-2.1_all.deb", + "package_sha256": "1330d25dfa5bab2e9b712b4950d2855cdb63a2b2b9451e2ffb93618c77e1f242", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt" + }, + { + "package": "fonts-noto-cjk", + "version": "1:20220127+repack1-1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-noto-cjk/fonts-noto-cjk_20220127+repack1-1_all.deb", + "package_sha256": "e804b3474a79bd70d5f03f590e2d06dbc5ce17f48be7cfaf6c48086471edd5be", + "license_file": "licenses/fonts-noto-cjk-20220127+repack1-1.txt" + }, + { + "package": "fonts-noto-core", + "version": "20201225-1build1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-noto/fonts-noto-core_20201225-1build1_all.deb", + "package_sha256": "653d237d5c4e8fcebb2710129ebbd7bf9bc248d03dfff23fcf261b0372fded69", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt" + } + ], + "files": [ + { + "family": "Caladea", + "style": "Bold", + "local_path": "files/Caladea-Bold.ttf", + "sha256": "74eda4fc5ffba0d8dc4aa76d41499f5ab76168d9ed6141c6417064c6244db9b6", + "package": "fonts-crosextra-caladea", + "package_version": "20130214-2.1", + "license": "Apache-2.0", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt" + }, + { + "family": "Caladea", + "style": "BoldItalic", + "local_path": "files/Caladea-BoldItalic.ttf", + "sha256": "f47a35ad6cd0efa9914d93f9d03c93e30c55da43674bccfabac73b3c0d522c01", + "package": "fonts-crosextra-caladea", + "package_version": "20130214-2.1", + "license": "Apache-2.0", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt" + }, + { + "family": "Caladea", + "style": "Italic", + "local_path": "files/Caladea-Italic.ttf", + "sha256": "9c968bf60ba1e851cdfea77c71e3540c57792f77482dd241acc29d1425569c4e", + "package": "fonts-crosextra-caladea", + "package_version": "20130214-2.1", + "license": "Apache-2.0", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt" + }, + { + "family": "Caladea", + "style": "Regular", + "local_path": "files/Caladea-Regular.ttf", + "sha256": "d2f6cad33f191e65b68bd74e6d4f7708080a41b32db635866109df3090265d91", + "package": "fonts-crosextra-caladea", + "package_version": "20130214-2.1", + "license": "Apache-2.0", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt" + }, + { + "family": "Carlito", + "style": "Bold", + "local_path": "files/Carlito-Bold.ttf", + "sha256": "0f62ab34ad5d079a0a28fac01bcf7c7a724a4db4d6cb99cab9cabff382fbb80f", + "package": "fonts-crosextra-carlito", + "package_version": "20130920-1.1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt" + }, + { + "family": "Carlito", + "style": "BoldItalic", + "local_path": "files/Carlito-BoldItalic.ttf", + "sha256": "380764b6898d7b73ceae6384b2958b196d2a0428962ef3adf138d27947228666", + "package": "fonts-crosextra-carlito", + "package_version": "20130920-1.1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt" + }, + { + "family": "Carlito", + "style": "Italic", + "local_path": "files/Carlito-Italic.ttf", + "sha256": "718a0663864d37a4868220a19b9668a5fe10a46197f6df367b4c2c30c04c026c", + "package": "fonts-crosextra-carlito", + "package_version": "20130920-1.1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt" + }, + { + "family": "Carlito", + "style": "Regular", + "local_path": "files/Carlito-Regular.ttf", + "sha256": "b4ff23ba370cc95a3c349336b73f9c28514a1371210f89832efc85c4b1ea7131", + "package": "fonts-crosextra-carlito", + "package_version": "20130920-1.1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt" + }, + { + "family": "Liberation Mono", + "style": "Bold", + "local_path": "files/LiberationMono-Bold.ttf", + "sha256": "410af69b6297b7cf6d20dd004004bd1bdb46460a60f9fef69b04169f4ff09660", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Mono", + "style": "BoldItalic", + "local_path": "files/LiberationMono-BoldItalic.ttf", + "sha256": "a2ab7fe6f5bd7c2bc59ca7f5f4212f165dc174cbbab366cab171df4e73939aa2", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Mono", + "style": "Italic", + "local_path": "files/LiberationMono-Italic.ttf", + "sha256": "1b09e2a1d70adf339048943b21037462c56108411817bf6988c86cb88289fc34", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Mono", + "style": "Regular", + "local_path": "files/LiberationMono-Regular.ttf", + "sha256": "babd36837e644f08e6ba09b69feb770fbeba9e4611a619e5471fb8dbc132d42c", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Sans", + "style": "Bold", + "local_path": "files/LiberationSans-Bold.ttf", + "sha256": "c2d334cafbd28522007cc16970db8db4a75256123594a43fe07f89cfceb5bacc", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Sans", + "style": "BoldItalic", + "local_path": "files/LiberationSans-BoldItalic.ttf", + "sha256": "2e5f6a48571d50f277598c533dea4f659abce53335fb475aa2bc45bd2527f1d0", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Sans", + "style": "Italic", + "local_path": "files/LiberationSans-Italic.ttf", + "sha256": "f71f02009bd7320571db05b7459c7db92a1f5f68ac619009a2f637e18c7a93f9", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Sans", + "style": "Regular", + "local_path": "files/LiberationSans-Regular.ttf", + "sha256": "36efda825bcd7d1de846204c3adad51ced9d9b5cb7df571fb33edc21207e324a", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Serif", + "style": "Bold", + "local_path": "files/LiberationSerif-Bold.ttf", + "sha256": "cfbe3d2edd46ae844b7eb95012f9274776801873e27b2230bbf751645f011888", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Serif", + "style": "BoldItalic", + "local_path": "files/LiberationSerif-BoldItalic.ttf", + "sha256": "23d013c7c9708b09be7517ddc3bff8322c5dfa16c629a68f6be2a860e2693698", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Serif", + "style": "Italic", + "local_path": "files/LiberationSerif-Italic.ttf", + "sha256": "2d826fdde37518f7393052764703fc8ec120ef1e19ba49b50fcc6b6186b8aa78", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Liberation Serif", + "style": "Regular", + "local_path": "files/LiberationSerif-Regular.ttf", + "sha256": "8d6951ea5fc4a9656df4802227292c7943186364929f00b97629e70daf228439", + "package": "fonts-liberation", + "package_version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt" + }, + { + "family": "Noto Sans", + "style": "Bold", + "local_path": "files/NotoSans-Bold.ttf", + "sha256": "e83493c945848ecd4a9ad0f6d19164541a0d3e23a9c952304a00a46e00272ac5", + "package": "fonts-noto-core", + "package_version": "20201225-1build1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt" + }, + { + "family": "Noto Sans", + "style": "Regular", + "local_path": "files/NotoSans-Regular.ttf", + "sha256": "89c3c497f618fdaa0b2d1e98fef93582f28c71debd2c4a8cdf41f190ced2909d", + "package": "fonts-noto-core", + "package_version": "20201225-1build1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt" + }, + { + "family": "Noto Sans Arabic", + "style": "Bold", + "local_path": "files/NotoSansArabic-Bold.ttf", + "sha256": "ded6fc7359ca36d15d7aab9ef0c066e21ce48b26a069994d6602fa2cb9a1b952", + "package": "fonts-noto-core", + "package_version": "20201225-1build1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt" + }, + { + "family": "Noto Sans Arabic", + "style": "Regular", + "local_path": "files/NotoSansArabic-Regular.ttf", + "sha256": "504d7407d86875acf7d04dfaa0fd7524d0b8797723bc4aa18022f29db25b0b6e", + "package": "fonts-noto-core", + "package_version": "20201225-1build1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt" + }, + { + "family": "Noto Sans CJK JP", + "style": "Bold", + "local_path": "files/NotoSansCJK-Bold.ttc", + "sha256": "faa5f3656a78b2e2d450d27fe8382c778bc2b6bb5ea29c986664a6a435056ceb", + "package": "fonts-noto-cjk", + "package_version": "1:20220127+repack1-1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-cjk-20220127+repack1-1.txt" + }, + { + "family": "Noto Sans CJK JP", + "style": "Regular", + "local_path": "files/NotoSansCJK-Regular.ttc", + "sha256": "b76b0433203017ca80401b2ee0dd69350349871c4b19d504c34dbdd80541690a", + "package": "fonts-noto-cjk", + "package_version": "1:20220127+repack1-1", + "license": "OFL-1.1", + "license_file": "licenses/fonts-noto-cjk-20220127+repack1-1.txt" + } + ] +} diff --git a/acidslide-v1/benchmark/prompts/DESIGNER_BRIEF.md b/acidslide-v1/benchmark/prompts/DESIGNER_BRIEF.md index 609051c..f350795 100644 --- a/acidslide-v1/benchmark/prompts/DESIGNER_BRIEF.md +++ b/acidslide-v1/benchmark/prompts/DESIGNER_BRIEF.md @@ -1,21 +1,20 @@ -# AcidSlide v1 — Gold Deck Designer Brief +# AcidSlide v1 — Canonical Deck Authoring Brief ## What This Document Is -You are building the **gold standard PowerPoint deck** for AcidSlide, a public benchmark that tests whether AI models can generate presentation slides. Every slide you create will be compared against AI-generated submissions — pixel by pixel, object by object. Your deck IS the answer key. +You are building the **canonical AcidSlide v1 reference deck**, a public benchmark target for presentation-generation systems. Every submitted deck is compared with this reference under the pinned LibreOffice renderer and by OOXML inspection. -This document specifies exactly what each slide must contain. Follow it precisely. +This prompt suite is the primary requirements contract and was authored before the reference deck. Reference images are supplementary visual guidance only: explicit prompt requirements take precedence. Follow this brief precisely and do not infer hidden constraints from any reference export. --- ## Critical Rules (Read Before Starting) ### Tool -- **Author in Microsoft PowerPoint** (desktop version preferred). You may use your normal PowerPoint workflow. -- **IMPORTANT — LibreOffice certification pass required**: The benchmark grades submissions using LibreOffice Impress (not PowerPoint). After you finish authoring, you (or we) will open your deck in LibreOffice Impress and fix anything that renders differently. The final gold deck is whatever looks correct in LibreOffice. -- This means: build in PowerPoint for productivity, but **do not rely on any PowerPoint-specific rendering behavior** that might not carry over. Stick to the fonts, colors, and constructs specified below and it will translate cleanly. -- Do NOT use Google Slides or Keynote. -- You do NOT need to install LibreOffice yourself — we handle the certification pass. +- **Author from a new document in the pinned LibreOffice Impress environment.** Save directly as `.pptx`; do not begin from or round-trip an existing PowerPoint-authored file. +- The official render is the PNG export produced by the pinned LibreOffice environment. Inspect that export while authoring and correct any text wrapping, chart formatting, spacing, or field issues there. +- Use only standards-based constructs that LibreOffice writes as native OOXML. Do not use Microsoft PowerPoint, Google Slides, or Keynote in the canonical authoring workflow. +- The deck must be reproducible from these prompts, bundled assets, and bundled fonts without consulting the gold deck. ### Slide Size - **16:9 widescreen** (33.867 cm × 19.05 cm / 13.333" × 7.5") @@ -33,19 +32,16 @@ You may ONLY use fonts from this exact list. Do not use ANY other fonts, not eve | **Caladea** | Serif headings | Metric-compatible with Cambria | | **Noto Sans** | Multilingual content (Latin) | | | **Noto Sans Arabic** | Arabic text | RTL support | -| **Noto Sans JP** | Japanese text | CJK support | -| **Noto Sans CJK JP** | Japanese text (alternate) | CJK support | +| **Noto Sans CJK JP** | Japanese text | CJK support; family exposed by the bundled TTC | -If a font is not installed on your system, install it before starting: -- Carlito: https://fonts.google.com/specimen/Carlito -- Caladea: https://fonts.google.com/specimen/Caladea -- Noto fonts: https://fonts.google.com/noto -- Liberation fonts: https://github.com/liberationfonts/liberation-fonts/releases +Install these exact files from `benchmark/fonts/files/` before authoring. Do not +download or substitute a similarly named font: `benchmark/fonts/manifest.json` +is the authoritative family, package-version, and SHA-256 inventory. ### Images and Assets -- Do NOT use any images not explicitly listed in this brief. -- All images will be provided to you in the `assets/` folder. -- Do NOT download images from the internet. +- Use an image only when its exact repository path is named by a canonical slide prompt and the corresponding path relative to `benchmark/assets/` appears as `local_path` in `benchmark/assets/manifest.json`. +- Do not infer an image allowance from `DESIGNER_BRIEF.md`, a reference image, or any external source. +- Do not download images from the internet. ### What NOT To Do - NO SmartArt @@ -63,6 +59,8 @@ If a font is not installed on your system, install it before starting: The entire deck must follow a consistent design language: +A more specific canonical slide clause overrides a deck-wide default only for the property it explicitly names. All other deck-wide defaults remain mandatory. This precedence rule applies to typography, color, layout, and local overrides. + ### Color Palette | Role | Color | Hex | |------|-------|-----| @@ -104,7 +102,7 @@ The entire deck must follow a consistent design language: - Based on AcidSlide Master - Title placeholder: top-left, Carlito 36pt Bold, `#FFFFFF` - Body placeholder: below title, Liberation Sans 18pt, `#F5F3EE` -- Accent bar: 4px wide vertical bar on left edge, `#E8634A` +- Accent bar: 0.070556cm wide vertical bar on the left edge, `#E8634A`. This equals 4 pixels in the official 1920×1080 export; the physical width is the authoring requirement. #### Layout 3: "Two-Column" - Based on AcidSlide Master @@ -138,10 +136,7 @@ The entire deck must follow a consistent design language: Benchmark for Slide Generation Fidelity ``` -4. **Hero image**: Place the image `assets/hero-abstract.png` (will be provided) in the right half of the slide. - - Position: x=17cm, y=2cm - - Size: width=15cm (height proportional) - - **Crop**: crop the left 20% of the image so it bleeds from mid-slide to right edge +4. **Hero image**: Place `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Keep that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is exactly the slide's right edge. - The image should overlap with decorative shapes (see below) 5. **Decorative shapes** (3 overlapping rounded rectangles): @@ -195,14 +190,11 @@ The entire deck must follow a consistent design language: - Line spacing: 1.2× for Level 1, 1.0× for Level 2 - Paragraph spacing: 6pt after each Level 1 item -4. **Grouped icon-text rows** on the right side (create as a GROUP of objects): - - Three rows, each containing: - - A small circle (1cm diameter) filled with `#2AACB8` - - Text to the right: "09:00", "11:30", "14:00" in Liberation Sans 14pt Bold `#FFFFFF` - - Rows evenly spaced vertically, aligned to the right margin - - All three rows MUST be grouped as a single group object + Use native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs. -5. **Alignment**: the grouped time column's top should align with the first bullet item. The bottom should align with the last bullet item. +4. **Grouped icon-text rows**: Create three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored. + - The three time labels, from top to bottom, are "09:00", "11:30", and "14:00" in Liberation Sans 14pt Bold `#FFFFFF`. + - Each circle is filled with `#2AACB8`. **Why this slide is hard for AI:** - Tests bullet hierarchy (indentation, different bullet characters) @@ -245,7 +237,7 @@ The entire deck must follow a consistent design language: - Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for "Metric", centered for all others - Cell padding: 0.3cm on all sides - Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` below header row - - Target column: any cell meeting target should have text in `#2AACB8`, missing target in `#E8634A` + - Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold. - Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓) 3. **Annotation callout** — a rounded rectangle with text, positioned next to the table: @@ -254,9 +246,9 @@ The entire deck must follow a consistent design language: - Fill: `#E8634A` - Corner radius: 0.3cm - Text: "Throughput target\nmissed by 5.5%" in Liberation Sans 12pt Bold `#FFFFFF`, centered - - A thin line (1pt, `#E8634A`) connecting the callout to the Throughput row + - A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained. -4. **Tab stops**: the "Metric" column text should use a 0.5cm left indent (not just cell padding — actual paragraph indent within the cell). +4. **Paragraph indent**: the Metric-column paragraphs must use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required. **Why this slide is hard for AI:** - Tests native table creation (not shapes) @@ -294,10 +286,10 @@ The entire deck must follow a consistent design language: - 2023 bars: `#1B2A4A` (navy) - 2024 bars: `#E8634A` (coral) - Chart title: "Annual Revenue by Region" in Carlito 16pt Bold - - X-axis labels: Liberation Sans 12pt, `#2D2D2D` - - Y-axis labels: Liberation Sans 11pt, `#2D2D2D`, format as "$0M" + - X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`. + - Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`. - Legend: bottom of chart, Liberation Sans 11pt - - Gridlines: horizontal only, `#E0E0E0` 0.5pt + - Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt. - No chart border - Background: transparent (slide background shows through) @@ -415,8 +407,8 @@ This slide's purpose is to verify that the master/layout is being used correctly - **CRITICAL**: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL. **Column 3 — Japanese** (right third): - - Title: "グローバルな視点" in Noto Sans JP 24pt Bold `#FFFFFF` - - Body (Noto Sans JP 14pt `#F5F3EE`, left-aligned): + - Title: "グローバルな視点" in Noto Sans CJK JP 24pt Bold `#FFFFFF` + - Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned): ``` 言語モデルの急速な進歩により、組織がドキュメント生成に 取り組む方法が変革されました。財務報告からマーケティング @@ -455,17 +447,17 @@ This slide's purpose is to verify that the master/layout is being used correctly 1. **Three images** from the asset manifest, each cropped differently: - - **Image A**: `assets/cityscape.png` + - **Image A**: `benchmark/assets/mirrored/cityscape.png` - Size on slide: 10cm × 8cm, position (1.5cm, 2cm) - Crop: remove top 15% and bottom 10% of original image - No shape mask - - **Image B**: `assets/cityscape.png` (same image, different crop) + - **Image B**: `benchmark/assets/mirrored/cityscape.png` (same image, different crop) - Size on slide: 8cm × 8cm, position (13cm, 2cm) - Crop: remove left 30% of original image - Apply **circle crop mask** (crop to ellipse shape) - - **Image C**: `assets/texture-pattern.png` + - **Image C**: `benchmark/assets/mirrored/texture-pattern.png` - Size on slide: 10cm × 8cm, position (22.5cm, 2cm) - Crop: remove right 25% of original image - Apply **rounded rectangle crop mask** with 1cm corner radius @@ -575,15 +567,10 @@ This slide's purpose is to verify that the master/layout is being used correctly "total": 142, "has_more": true ) - - NOTE TO DESIGNER: The parentheses above represent - JSON curly braces in the actual slide text. When - typing this content into the slide, use standard - JSON curly braces, i.e., the opening and closing - brace characters. They are written as parentheses - here only because this brief avoids those characters. ``` + Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Preserve all other characters. + **Right column** — text box WITH auto-shrink enabled: - AutoFit: Shrink text on overflow = ON - Same text content as left column but with this additional block appended: @@ -631,16 +618,18 @@ This slide's purpose is to verify that the master/layout is being used correctly |-----|-------|----------|------| | Client | "Client App" | (2cm, 3cm) | `#2AACB8` | | API Gateway | "API Gateway" | (14cm, 3cm) | `#1B2A4A` | - | Auth | "Auth Service" | (10cm, 9cm) | `#E8634A` | - | Grader | "Grader" | (18cm, 9cm) | `#E8634A` | + | Auth | "Auth Service" | (8cm, 9cm) | `#E8634A` | + | Grader | "Grader" | (20cm, 9cm) | `#E8634A` | | Queue | "Job Queue" | (14cm, 9cm) | `#D4A843` | | Storage | "Object Store" | (14cm, 15cm) | `#1B2A4A` | | DB | "PostgreSQL" | (6cm, 15cm) | `#1B2A4A` | | LB | "Leaderboard" | (22cm, 15cm) | `#2AACB8` | + No pair of architecture boxes overlaps. + All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered. -2. **Connectors** — use native connectors (Insert → Shapes → Connectors in PowerPoint, or Insert → Connector in LibreOffice), NOT plain lines: +2. **Connectors** — use native connectors (Insert → Connector in LibreOffice), NOT plain lines: - Client → API Gateway (straight connector, arrow at end) - API Gateway → Auth (elbow connector, arrow at end) - API Gateway → Queue (straight connector, arrow at end) @@ -680,7 +669,7 @@ This slide's purpose is to verify that the master/layout is being used correctly 1. **Title** (placeholder): `Brand Colors` -2. **Six color swatches** in a row — each is a rounded rectangle (4cm × 4cm): +2. **Six color swatches in two rows of three** — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row. **Top row — inherited from theme/master** (these must use theme color references, NOT hardcoded hex): - Swatch 1: Theme Primary color @@ -721,14 +710,12 @@ This slide's purpose is to verify that the master/layout is being used correctly 2. **Three field demonstrations** — each in its own text box: **Field 1 — Slide Number**: - - Text box: "Current slide: " followed by an **inserted slide number field** (PowerPoint: Insert → Slide Number; LibreOffice: Insert → Field → Page Number) + - Text box: "Current slide: " followed by an **inserted slide number field** (LibreOffice: Insert → Field → Page Number) - Do NOT type the number manually. It MUST be a live field. - Liberation Sans 18pt `#FFFFFF` **Field 2 — Date/Time**: - - Text box: "Generated: " followed by an **inserted date/time field** (PowerPoint: Insert → Date & Time; LibreOffice: Insert → Field → Date/Time, fixed format) - - Use fixed date format (not auto-updating) - - Liberation Sans 18pt `#FFFFFF` + - `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed exactly as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`. **Field 3 — Footer**: - The slide footer (from View → Header and Footer) should contain: "AcidSlide Benchmark v1" @@ -765,7 +752,7 @@ Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors. ### SLIDE 17: Deep Grouping -3 levels of nested groups. Inner groups contain 3-4 shapes each. Middle groups contain 2-3 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level. +3 levels of nested groups. Inner groups contain exactly 3 shapes each. Middle groups contain exactly 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level. ### SLIDE 18: Multi-Column Editorial 3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column. @@ -780,24 +767,24 @@ Everything combined: chart (line chart), table (3×6), approved image (cropped), ## Asset Manifest -The following images will be provided in `assets/`. Do NOT use any other images. +The following images are bundled in `benchmark/assets/mirrored/`. Do NOT use any other images. | Filename | Description | Approximate Size | |----------|-------------|------------------| | `hero-abstract.png` | Abstract geometric art for Slide 1 cover | 1920×1080 | -| `cityscape.png` | Urban skyline photograph for Slide 7 crops | 2400×1600 | +| `cityscape.png` | Procedural urban skyline illustration for image-crop tests | 2400×1600 | | `texture-pattern.png` | Geometric texture for Slide 7 and Slide 18 | 800×800 | -*Assets will be delivered separately in the `assets/mirrored/` directory.* +*Assets are bundled in `benchmark/assets/mirrored/`; hashes and source metadata are recorded in the manifest.* --- -## Delivery +## Delivery and Validation -### Step 1: Designer delivers PowerPoint file -Deliver the completed file as `acidslide-v1-gold.pptx` +### Step 1: Author delivers the canonical reference deck +Deliver the prompt-authored file as `acidslide-v1-gold.pptx` from the pinned LibreOffice environment. -### Step 2: Designer self-check +### Step 2: Author self-check Verify before delivery: - [ ] All fonts are from the approved list above - [ ] All images are from the asset manifest above @@ -814,20 +801,12 @@ Verify before delivery: - [ ] Slide number on every slide comes from the master, not manually typed - [ ] Groups on Slides 2, 5, 8, 10, 17 are actual group objects -### Step 3: LibreOffice certification pass (we handle this) -After delivery, we will: -1. Open the .pptx in LibreOffice Impress 7.6+ -2. Export all slides to PNG and visually compare against what PowerPoint shows -3. Fix any rendering differences (text wrapping, chart formatting, spacing) -4. Save the LibreOffice-certified version as the final gold deck -5. Re-export final reference PNGs from LibreOffice - -**You may be asked to make revisions** if structural elements (masters, layouts, groups, tables, charts, fields) don't translate cleanly to LibreOffice. This is rare if you stick to the approved fonts and standard features above. - -### Known PowerPoint → LibreOffice differences to avoid -- **Do NOT use "Calibri" or "Cambria"** — use Carlito and Caladea instead (they're metric-compatible and render identically) -- **Do NOT use PowerPoint's "Morph" transition** — not supported -- **Do NOT use 3D rotation or bevel effects** — render differently -- **Do NOT use SmartArt** — already excluded above, but worth repeating since it's completely broken in LibreOffice -- **Charts**: keep formatting simple (no 3D effects, custom leader lines, or complex axis formatting). Basic bar/line/pie charts translate well. -- **Shadows**: basic outer shadows translate well. Avoid complex "glow" or "reflection" effects. +### Step 3: Canonical environment certification +After delivery, the benchmark maintainer will: +1. Open the `.pptx` in the pinned LibreOffice environment without document recovery. +2. Export all 20 slides to PNG at 1920×1080. +3. Run OOXML schema, structural, font, asset-hash, and anti-cheat validation. +4. Run repeated exports to establish deterministic self-similarity. +5. Publish grading-verified measurements separately from generation-attested metadata supplied by model submitters. + +The file must not contain Calibri, Cambria, SmartArt, transitions, 3D rotation, or bevel effects. Use the bundled metric-compatible fonts and native constructs defined above. Keep charts standards-based and use only basic outer shadows; avoid glow and reflection effects. diff --git a/acidslide-v1/benchmark/prompts/deck.md b/acidslide-v1/benchmark/prompts/deck.md new file mode 100644 index 0000000..d27566f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/deck.md @@ -0,0 +1,111 @@ +# AcidSlide v1 — Deck-Level Prompt + +This prompt is the primary deck-wide requirements contract. It is authored independently of the reference deck; reference PNGs are supplementary guidance only. Build a new `.pptx` from these instructions in the pinned LibreOffice environment. + +## Critical Rules (Read Before Starting) + +### Tool +- **Author from a new document in the pinned LibreOffice Impress environment.** Save directly as `.pptx`; do not begin from or round-trip an existing PowerPoint-authored file. +- The official render is the PNG export produced by the pinned LibreOffice environment. Inspect that export while authoring and correct any text wrapping, chart formatting, spacing, or field issues there. +- Use only standards-based constructs that LibreOffice writes as native OOXML. Do not use Microsoft PowerPoint, Google Slides, or Keynote in the canonical authoring workflow. +- The deck must be reproducible from these prompts, bundled assets, and bundled fonts without consulting the gold deck. + +### Slide Size +- **16:9 widescreen** (33.867 cm × 19.05 cm / 13.333" × 7.5") +- Set this before creating any slides: Slide → Slide Properties → Width/Height + +### Fonts — ONLY USE THESE +You may ONLY use fonts from this exact list. Do not use ANY other fonts, not even system defaults. + +| Font | Use For | Notes | +|------|---------|-------| +| **Liberation Sans** | Body text, labels, UI elements | Metric-compatible with Arial | +| **Liberation Serif** | Serif body text, formal content | Metric-compatible with Times New Roman | +| **Liberation Mono** | Code, monospaced content | Metric-compatible with Courier New | +| **Carlito** | Headings, titles | Metric-compatible with Calibri | +| **Caladea** | Serif headings | Metric-compatible with Cambria | +| **Noto Sans** | Multilingual content (Latin) | | +| **Noto Sans Arabic** | Arabic text | RTL support | +| **Noto Sans CJK JP** | Japanese text | CJK support; family exposed by the bundled TTC | + +Install these exact files from `benchmark/fonts/files/` before authoring. Do not +download or substitute a similarly named font: `benchmark/fonts/manifest.json` +is the authoritative family, package-version, and SHA-256 inventory. + +### Images and Assets +- Use an image only when its exact repository path is named by a canonical slide prompt and the corresponding path relative to `benchmark/assets/` appears as `local_path` in `benchmark/assets/manifest.json`. +- Do not infer an image allowance from `DESIGNER_BRIEF.md`, a reference image, or any external source. +- Do not download images from the internet. + +### What NOT To Do +- NO SmartArt +- NO animations or transitions +- NO video or audio +- NO speaker notes +- NO comments +- NO hidden slides +- NO vertical East Asian text layout +- NO embedded macros or scripts + +--- + +## Deck-Level Design System + +The entire deck must follow a consistent design language: + +A more specific canonical slide clause overrides a deck-wide default only for the property it explicitly names. All other deck-wide defaults remain mandatory. This precedence rule applies to typography, color, layout, and local overrides. + +### Color Palette +| Role | Color | Hex | +|------|-------|-----| +| Primary | Deep navy | `#1B2A4A` | +| Secondary | Warm coral | `#E8634A` | +| Accent 1 | Bright teal | `#2AACB8` | +| Accent 2 | Gold/amber | `#D4A843` | +| Background (dark slides) | Near-black | `#0F1923` | +| Background (light slides) | Off-white | `#F5F3EE` | +| Text on dark | White | `#FFFFFF` | +| Text on light | Charcoal | `#2D2D2D` | + +### Typography Scale +| Element | Font | Size | Weight | +|---------|------|------|--------| +| Slide title | Carlito | 36pt | Bold | +| Subtitle | Carlito | 24pt | Regular | +| Body text | Liberation Sans | 18pt | Regular | +| Small text/labels | Liberation Sans | 14pt | Regular | +| Caption | Liberation Sans | 12pt | Italic | +| Code | Liberation Mono | 14pt | Regular | + +### Master Slides and Layouts + +**You MUST create the following masters/layouts before building slides.** Some slides specifically test whether AI models correctly use masters rather than copying elements manually. + +#### Master: "AcidSlide Master" +- Background: solid `#0F1923` +- Slide number placeholder in bottom-right corner: Liberation Sans 10pt, `#FFFFFF` at 50% opacity +- Thin horizontal line (0.5pt, `#2AACB8`) at y=17.5cm spanning full width +- Company name "ACIDSLIDE" in bottom-left: Liberation Sans 8pt, `#FFFFFF` at 30% opacity + +#### Layout 1: "Title Slide" +- Based on AcidSlide Master +- Title placeholder: centered, Carlito 44pt Bold, `#FFFFFF` +- Subtitle placeholder: centered below title, Carlito 24pt, `#E8634A` + +#### Layout 2: "Content Slide" +- Based on AcidSlide Master +- Title placeholder: top-left, Carlito 36pt Bold, `#FFFFFF` +- Body placeholder: below title, Liberation Sans 18pt, `#F5F3EE` +- Accent bar: 0.070556cm wide vertical bar on the left edge, `#E8634A`. This equals 4 pixels in the official 1920×1080 export; the physical width is the authoring requirement. + +#### Layout 3: "Two-Column" +- Based on AcidSlide Master +- Title placeholder: top, Carlito 36pt Bold, `#FFFFFF` +- Left body placeholder: left half +- Right body placeholder: right half + +#### Layout 4: "Blank with Footer" +- Based on AcidSlide Master +- No content placeholders (only the master footer elements) + +--- diff --git a/acidslide-v1/benchmark/prompts/validation/slide-01.md b/acidslide-v1/benchmark/prompts/validation/slide-01.md new file mode 100644 index 0000000..172d06d --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-01.md @@ -0,0 +1,30 @@ + +# Slide 01 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `48ce312215ea5dd2301719001fd72474946b252390643ee92a84574f49a3055b` +- Paraphrase A SHA-256: `df76e61dbd7598ff28c485a4fef4ada465f3028b37d973f12c76cdf7172230e0` +- Paraphrase B SHA-256: `e0e6cd11769f75eae8aedc33d4c85aa2fb8d181f0afd7459fc147e2311492493` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-02.md b/acidslide-v1/benchmark/prompts/validation/slide-02.md new file mode 100644 index 0000000..44407cc --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-02.md @@ -0,0 +1,30 @@ + +# Slide 02 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `1b6d34909a8dd6ef996e67a0f683692e67b507bfa21e9099ab9486ed64e6651e` +- Paraphrase A SHA-256: `49d4de1acb350a4f5c2f767ff6fe2b2644d2abecc45298fe729ae26b9daf0e53` +- Paraphrase B SHA-256: `8a5c892bf119932f222bd35ee2e1a8b903cbd4f7b56fa8d6a5b867c0601f174d` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-03.md b/acidslide-v1/benchmark/prompts/validation/slide-03.md new file mode 100644 index 0000000..b999ae0 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-03.md @@ -0,0 +1,30 @@ + +# Slide 03 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `86ffb3b47398d048539e659e88a0c1074152a51f212aec16acebdc3b6db755c5` +- Paraphrase A SHA-256: `cfa6e7d59aeb1822335d49595aaa1ef1b578ee57acc21a3ae189a89ebc92bdf3` +- Paraphrase B SHA-256: `2c79103ad8a03c15347de27c56e1b003e0da8c4d9a4f56254dd52d01d729b054` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-04.md b/acidslide-v1/benchmark/prompts/validation/slide-04.md new file mode 100644 index 0000000..53cee25 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-04.md @@ -0,0 +1,30 @@ + +# Slide 04 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `1cc1a7b72a0780e13a564111e6e1a30e53e818fdd7d53675f3d20a84fbe03b1f` +- Paraphrase A SHA-256: `a6c7257409407e1b45a96c4e4c2cffeea6d76e504fdfd1fcebe7bef568df432e` +- Paraphrase B SHA-256: `c54515c9433ad0ae980433c9834d0061cf322dd36c471e0917e512f0df796205` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-05.md b/acidslide-v1/benchmark/prompts/validation/slide-05.md new file mode 100644 index 0000000..8a4ce10 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-05.md @@ -0,0 +1,30 @@ + +# Slide 05 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `8f9a7d82cfd6c687f55f14cd1addf8f2d2c00662aac21a499aa34b95ff12750c` +- Paraphrase A SHA-256: `2f8471d11d5c69e96cbec77703b66882d5cdba5c865a853ac55562a1eea6fc3c` +- Paraphrase B SHA-256: `a86474279d615df43241b1c3908a85ab5e6468d5b16cc5af99d41b0ca587db51` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-06.md b/acidslide-v1/benchmark/prompts/validation/slide-06.md new file mode 100644 index 0000000..1943dcf --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-06.md @@ -0,0 +1,30 @@ + +# Slide 06 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `a1d035b57f759fe162ee1707ddf316b886a24f217f5677b878973198e0127592` +- Paraphrase A SHA-256: `bff711a0a508c5a64c399ee06d61317302fdc4a682f99034d77df377926d3bf9` +- Paraphrase B SHA-256: `b72d32e1fe636cd80a7fd03255887a33a445b1a38e64f8f73cd7cda8036b7018` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-07.md b/acidslide-v1/benchmark/prompts/validation/slide-07.md new file mode 100644 index 0000000..629ab44 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-07.md @@ -0,0 +1,30 @@ + +# Slide 07 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `558958a1925810b8ffad53d07ae297675916d14d757f829ac005e99ada4a0210` +- Paraphrase A SHA-256: `c7cbe77cbbb83b82b1f1fa797518ab0fe7d75bc067bbb4e4ded27efd08a2cd3f` +- Paraphrase B SHA-256: `d1618f9b2471681712bc415b6d31d5329ac0f2b4beb110bf8ef39b3c7b65a618` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-08.md b/acidslide-v1/benchmark/prompts/validation/slide-08.md new file mode 100644 index 0000000..4be8d57 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-08.md @@ -0,0 +1,30 @@ + +# Slide 08 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `f9e89d1564b307475a5eac1bf51b502838f4894dee14f1238c6463326f3df4a7` +- Paraphrase A SHA-256: `0707bf6e52ff4d18ec84857517c0d9d69c2afa4b1b42c567828fb2127b77bceb` +- Paraphrase B SHA-256: `d929df4103244a6fdd9b47d3813dd1986df1e5ad34b21f5eed0cf6beee046018` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-09.md b/acidslide-v1/benchmark/prompts/validation/slide-09.md new file mode 100644 index 0000000..af517b3 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-09.md @@ -0,0 +1,30 @@ + +# Slide 09 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `57896c563e2761dd90eea8b40e94511cb6d80c710be8a68e6e8c5eee94c4f2a6` +- Paraphrase A SHA-256: `1af4c47a917b2e536b2f1ad95773b5a5e35f047c623524aa3c9a4fb580a0a9ea` +- Paraphrase B SHA-256: `54f7f24199f5874161a1e25530f1dbbf4e5f0d31dddf82e307933c8f75222c9d` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-10.md b/acidslide-v1/benchmark/prompts/validation/slide-10.md new file mode 100644 index 0000000..44d42fe --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-10.md @@ -0,0 +1,30 @@ + +# Slide 10 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `006bf8acf3a012f34c9d01aa24431d63bb1194d128736eab3fd1c3553352fabf` +- Paraphrase A SHA-256: `388f3c97af5824d60fa4bb73d5d162a05967b0c220b0429ee9d3b07a0b43f6ad` +- Paraphrase B SHA-256: `5054c2987457d83c0bf514be43f125dee7917bb262ad0219a83f925a975279a5` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-11.md b/acidslide-v1/benchmark/prompts/validation/slide-11.md new file mode 100644 index 0000000..dded382 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-11.md @@ -0,0 +1,30 @@ + +# Slide 11 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `d2d0f303ddd4a8923cdf6988918505b37fbecb8d7f4e96cfbc29940010d36b89` +- Paraphrase A SHA-256: `a27edb91242b06f49cae2446ee1783538aff62a039ed8a9bf3f6e4ac2f0bda77` +- Paraphrase B SHA-256: `d2b337f3c595acd9b99dcd8946a3b6246617e1381462d5a1d1ddde84f298e3b4` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-12.md b/acidslide-v1/benchmark/prompts/validation/slide-12.md new file mode 100644 index 0000000..30f87b2 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-12.md @@ -0,0 +1,30 @@ + +# Slide 12 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `c43ff38821bdfa4e2f5cae337cd25f55099529eaeeb8eefe8a3fd2bffb771728` +- Paraphrase A SHA-256: `31dfd3b632acc2607437ff382621e2e507b56b763682a43d1d5f754ebcbc426e` +- Paraphrase B SHA-256: `fb47db9262f1dc3f481527b83c61473729936fd181c47f9c18142f67cc42bfa8` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-13.md b/acidslide-v1/benchmark/prompts/validation/slide-13.md new file mode 100644 index 0000000..84c5177 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-13.md @@ -0,0 +1,30 @@ + +# Slide 13 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `e9e56ffdd74f021765cd9a933503fda3103fc5e91d4cff56259d39463654b631` +- Paraphrase A SHA-256: `7b0854475062ae55fffa19786de5a6bb5045a56d6889e1d4f169577849385b1f` +- Paraphrase B SHA-256: `0f3a275cb5359c2aa184bd9763dd86e5d8af96f4aa48171f3d5e9bb456ffb1c3` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-14.md b/acidslide-v1/benchmark/prompts/validation/slide-14.md new file mode 100644 index 0000000..261f38f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-14.md @@ -0,0 +1,30 @@ + +# Slide 14 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `1c343788be39b16eeacc5f669794a8187608f0c037c631081f8d52066c013666` +- Paraphrase A SHA-256: `df9fbec40ead118b8266767a0d2c6fe34df32c2a4bbc4f622606a365a2e0e539` +- Paraphrase B SHA-256: `a91058ab785b02e919cf9ecba6d8a43a0e68dd4504953582f4eaa202bd45e3aa` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-15.md b/acidslide-v1/benchmark/prompts/validation/slide-15.md new file mode 100644 index 0000000..d6dbcfc --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-15.md @@ -0,0 +1,30 @@ + +# Slide 15 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `aaccdd6f2695aa115d95e995dd8a854d5d51acbe9f8af8146e329c8382942c07` +- Paraphrase A SHA-256: `3de26c4f298a0ea045c1cbfa437544cc9e1985e052bb7aa56b919429d83572fe` +- Paraphrase B SHA-256: `5fa3c2ef1bce7a73657bfb976acbc1fb480f60b1a5b17802144f6596a78f7076` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-16.md b/acidslide-v1/benchmark/prompts/validation/slide-16.md new file mode 100644 index 0000000..fec1fe5 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-16.md @@ -0,0 +1,30 @@ + +# Slide 16 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `1ca475aa23be5d7d3b0f8d03fc17e2b78c1886cc5a532d57aebc3f98ed71e2c2` +- Paraphrase A SHA-256: `c1b661d7de888e80b1468c0638bac17e9200c57dbffe7f3f1b85bbd9862dfe3b` +- Paraphrase B SHA-256: `c4ce2b8794ebe8d91c1cdd3fafd46aafe0347e347f3752ef194ec6898252919b` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-17.md b/acidslide-v1/benchmark/prompts/validation/slide-17.md new file mode 100644 index 0000000..5c4f224 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-17.md @@ -0,0 +1,30 @@ + +# Slide 17 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `80ad70a1f59d10f8d6f6b4b1c69c1c2b3abd84100891994b0332480cabc829c9` +- Paraphrase A SHA-256: `4176bc52f51ef82dc5af787394d5c992f344a251b45d74b18317537ab64c3a54` +- Paraphrase B SHA-256: `32767b82411995b57e745fe2dd3731ac4adfad16b941b7a017db85a0eaaf0bd9` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-18.md b/acidslide-v1/benchmark/prompts/validation/slide-18.md new file mode 100644 index 0000000..fccae3f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-18.md @@ -0,0 +1,30 @@ + +# Slide 18 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `158b1f1412de235a48f184256483a630d9baba154b5e493306f46e8888bedbb2` +- Paraphrase A SHA-256: `cdcd5d715ecb6bea2c2e3c55ad5a89df900c7d7374e7263e12a98f12fa1d65f8` +- Paraphrase B SHA-256: `23bd62703614a6e0caa7e9a7a085779b6cf25865512a014952677b0224f8a26d` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-19.md b/acidslide-v1/benchmark/prompts/validation/slide-19.md new file mode 100644 index 0000000..dfed36b --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-19.md @@ -0,0 +1,30 @@ + +# Slide 19 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `51b388342d0563450e15aad40ae0a584625ebdb159416146d4d9c1d1722898ee` +- Paraphrase A SHA-256: `89c290deea5eafe5a6de472eb2b284a0768838744f33281dc17d77f40a9c1462` +- Paraphrase B SHA-256: `3e149ffa5ba801474a59aebbeef7d87803a17391f1b5e1e1b36c0423de3738c9` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/validation/slide-20.md b/acidslide-v1/benchmark/prompts/validation/slide-20.md new file mode 100644 index 0000000..d0a35a0 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/validation/slide-20.md @@ -0,0 +1,30 @@ + +# Slide 20 prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: pass +- Canonical SHA-256: `5eefdbce232c0e666065c907020c0ea650014444ed431c67be8cde436b10ad50` +- Paraphrase A SHA-256: `89987a71046da3d440aa6e096b0125478a4ccbac36c0e56d2f9b07ac2396a78d` +- Paraphrase B SHA-256: `402c1979168b71c643ab180d7c6357a112f191ff5d2b37fca80ee45b8971d0cd` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-01.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-01.md new file mode 100644 index 0000000..b98493c --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-01.md @@ -0,0 +1,43 @@ +# AcidSlide v1 — Slide 01: Cover / Title Stress Test + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Title Slide" (from master) +**Tier:** Level 1 + +**What to build:** + +1. Use the "Title Slide" layout — the title and subtitle MUST come from the layout placeholders, not freestanding text boxes. + +2. **Title text** (in the title placeholder): + ``` + AcidSlide v1 + ``` + +3. **Subtitle text** (in the subtitle placeholder): + ``` + Benchmark for Slide Generation Fidelity + ``` + +4. **Hero image**: Place `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Keep that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is exactly the slide's right edge. + - The image should overlap with decorative shapes (see below) + +5. **Decorative shapes** (3 overlapping rounded rectangles): + - Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline + - Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline + - Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline + +6. **Z-order** (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text + +7. **Shadow**: Apply a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm. + +8. **Slide number**: must come from the master's slide number placeholder (do NOT type "1" manually). + +**Why this slide is hard for AI:** +- Tests placeholder usage (not manual text boxes) +- Tests precise crop rectangle on an image +- Tests z-order with overlapping semi-transparent shapes +- Tests shadow parameters +- Tests master-driven footer/slide number inheritance + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-02.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-02.md new file mode 100644 index 0000000..5cd5e79 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-02.md @@ -0,0 +1,48 @@ +# AcidSlide v1 — Slide 02: Dense Agenda with Layout Semantics + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**What to build:** + +1. Use the "Content Slide" layout. Title and body MUST be in the layout placeholders. + +2. **Title** (placeholder): `Agenda` + +3. **Body** (placeholder) — a bulleted list with specific formatting: + ``` + • Opening Remarks + ◦ Welcome and introductions + ◦ Safety briefing + • Technical Deep Dive + ◦ Architecture overview + ◦ Performance benchmarks + ◦ Security audit results + • Breakout Sessions + ◦ Track A: Infrastructure + ◦ Track B: Applications + • Closing & Next Steps + ``` + + - Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A` + - Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE` + - Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm + - Line spacing: 1.2× for Level 1, 1.0× for Level 2 + - Paragraph spacing: 6pt after each Level 1 item + + Use native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs. + +4. **Grouped icon-text rows**: Create three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored. + - The three time labels, from top to bottom, are "09:00", "11:30", and "14:00" in Liberation Sans 14pt Bold `#FFFFFF`. + - Each circle is filled with `#2AACB8`. + +**Why this slide is hard for AI:** +- Tests bullet hierarchy (indentation, different bullet characters) +- Tests paragraph-level formatting (spacing, indent) +- Tests object grouping (the time column must be one group) +- Tests placeholder usage for title and body +- Tests alignment precision + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-03.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-03.md new file mode 100644 index 0000000..3e477e6 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-03.md @@ -0,0 +1,56 @@ +# AcidSlide v1 — Slide 03: Native Table Stress Test + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 1 + +**What to build:** + +1. **Title text box** (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders): + - Text: `Performance Metrics` + - Font: Carlito 36pt Bold, `#FFFFFF` + - Position: x=1.5cm, y=0.8cm + +2. **Native table** — this MUST be a real LibreOffice Impress table, not shapes pretending to be a table: + - Position: x=1.5cm, y=3cm + - Size: 30cm × 12cm + - Rows: 7 (1 header + 6 data) + - Columns: 5 + + | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target | + |--------|---------|---------|---------|--------| + | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms | + | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms | + | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps | + | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% | + | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% | + | Cache Hit | 72% | 78% | 84% | ≥80% | + + **Table styling:** + - Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered + - Data rows: alternating `#0F1923` and `#161F2E` + - Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for "Metric", centered for all others + - Cell padding: 0.3cm on all sides + - Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` below header row + - Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold. + - Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓) + +3. **Annotation callout** — a rounded rectangle with text, positioned next to the table: + - Position: x=24cm, y=15.5cm + - Size: 8cm × 2.5cm + - Fill: `#E8634A` + - Corner radius: 0.3cm + - Text: "Throughput target\nmissed by 5.5%" in Liberation Sans 12pt Bold `#FFFFFF`, centered + - A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained. + +4. **Paragraph indent**: the Metric-column paragraphs must use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required. + +**Why this slide is hard for AI:** +- Tests native table creation (not shapes) +- Tests cell-level formatting (conditional colors) +- Tests table borders (mixed weights) +- Tests tab stops and paragraph indentation inside table cells +- Tests annotation positioning relative to table cells + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-04.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-04.md new file mode 100644 index 0000000..426f41b --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-04.md @@ -0,0 +1,71 @@ +# AcidSlide v1 — Slide 04: Native Chart Stress Test + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**What to build:** + +1. **Title** (placeholder): `Revenue Growth` + +2. **Native chart** — MUST be a real LibreOffice Impress chart, not shapes/images: + - Chart type: **Clustered bar chart** (horizontal bars) + - Position: x=1.5cm, y=3cm + - Size: 20cm × 14cm + + **Chart data:** + + | Region | 2023 Revenue ($M) | 2024 Revenue ($M) | + |--------|-------------------|--------------------| + | North America | 42.3 | 51.8 | + | Europe | 28.7 | 35.2 | + | Asia Pacific | 19.4 | 31.6 | + | Latin America | 8.1 | 12.4 | + | Middle East & Africa | 3.9 | 7.2 | + + **Chart formatting:** + - 2023 bars: `#1B2A4A` (navy) + - 2024 bars: `#E8634A` (coral) + - Chart title: "Annual Revenue by Region" in Carlito 16pt Bold + - X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`. + - Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`. + - Legend: bottom of chart, Liberation Sans 11pt + - Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt. + - No chart border + - Background: transparent (slide background shows through) + +3. **Callout shapes** — two overlaid callout annotations: + + - Callout 1: positioned over the "Asia Pacific 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#2AACB8` + - Text: "+62.9% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + + - Callout 2: positioned over the "Middle East & Africa 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#D4A843` + - Text: "+84.6% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + +4. **Supporting text block** to the right of the chart: + - Position: x=23cm, y=4cm + - Width: 9cm + - Text (Liberation Sans 14pt, `#F5F3EE`): + ``` + Key Takeaways: + + ▸ Total revenue up 38.2% YoY + ▸ APAC fastest-growing region + ▸ All regions exceeded targets + ``` + +**Why this slide is hard for AI:** +- Tests native chart creation with specific chart type +- Tests chart formatting (colors, labels, gridlines, legend) +- Tests chart data accuracy +- Tests overlay shapes on top of chart +- Tests connector arrows between callouts and chart elements + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-05.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-05.md new file mode 100644 index 0000000..34fb01f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-05.md @@ -0,0 +1,50 @@ +# AcidSlide v1 — Slide 05: Master Reuse Enforcement + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**What to build:** + +This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied. + +1. **Title** (placeholder): `Our Team` + +2. **Body content** — three team member cards arranged horizontally: + + Each card is a group containing: + - A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8` + - Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text "Photo" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos + - Name: Carlito 18pt Bold `#FFFFFF`, centered + - Title: Liberation Sans 14pt `#E8634A`, centered + - Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines + + **Card 1:** + - Name: "Sarah Chen" + - Title: "Chief Architect" + - Description: "15 years building distributed systems at scale" + + **Card 2:** + - Name: "Marcus Rivera" + - Title: "Head of Design" + - Description: "Formerly at Apple, obsessed with pixel-perfect interfaces" + + **Card 3:** + - Name: "Yuki Tanaka" + - Title: "ML Engineering Lead" + - Description: "PhD in NLP, built the model serving infrastructure" + + Cards positioned at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide. + +3. **Critical requirement**: The bottom footer line, "ACIDSLIDE" text, and slide number MUST come from the master. Do NOT manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited. + +4. **The accent bar** on the left edge must also come from the "Content Slide" layout, not a manually placed shape. + +**Why this slide is hard for AI:** +- Tests that repeated elements (footer, line, text, slide number) come from master inheritance +- Tests grouped objects (each card is a group) +- Tests precise horizontal distribution of equal-sized elements +- Tests placeholder text formatting within groups + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-06.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-06.md new file mode 100644 index 0000000..a20b585 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-06.md @@ -0,0 +1,65 @@ +# AcidSlide v1 — Slide 06: Multilingual Editorial + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 2 + +**What to build:** + +1. **Three text columns** side by side: + + **Column 1 — English** (left third): + - Title: "Global Perspectives" in Carlito 24pt Bold `#FFFFFF` + - Body (Liberation Sans 14pt `#F5F3EE`, left-aligned): + ``` + The rapid advancement of language models + has transformed how organizations approach + document generation. From financial reports + to marketing materials, AI-driven content + creation is reshaping every industry. + ``` + + **Column 2 — Arabic RTL** (center third): + - Title: "وجهات نظر عالمية" in Noto Sans Arabic 24pt Bold `#FFFFFF` + - Body (Noto Sans Arabic 14pt `#F5F3EE`, **RIGHT-to-left aligned**): + ``` + لقد أدى التقدم السريع في نماذج اللغة إلى تحويل + كيفية تعامل المؤسسات مع إنشاء المستندات. من + التقارير المالية إلى المواد التسويقية، يعيد إنشاء + المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة. + ``` + - **CRITICAL**: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL. + + **Column 3 — Japanese** (right third): + - Title: "グローバルな視点" in Noto Sans CJK JP 24pt Bold `#FFFFFF` + - Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned): + ``` + 言語モデルの急速な進歩により、組織がドキュメント生成に + 取り組む方法が変革されました。財務報告からマーケティング + 資料まで、AI主導のコンテンツ作成はあらゆる産業を + 再形成しています。 + ``` + +2. **Decorative separator lines** between columns: + - Vertical lines at x=11.2cm and x=22.5cm + - Height: from y=3cm to y=16cm + - Style: 1pt, `#2AACB8`, 50% opacity + +3. **Callout box** overlapping the Arabic and Japanese columns: + - Position: x=15cm, y=13cm + - Size: 12cm × 4cm + - Fill: `#E8634A` at 90% opacity + - Text: "AI-generated slides must handle RTL text,\nCJK line breaking, and mixed scripts correctly." + - Font: Liberation Sans 13pt Bold `#FFFFFF`, centered + - Corner radius: 0.3cm + - This callout should overlap both the Arabic and Japanese columns + +**Why this slide is hard for AI:** +- Tests correct RTL paragraph direction (not just alignment) +- Tests CJK text rendering and line breaking +- Tests correct font assignment per script +- Tests overlap between callout and text columns +- Tests Unicode text preservation (exact characters must match) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-07.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-07.md new file mode 100644 index 0000000..079e954 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-07.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 07: Image Crop and Mask + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**What to build:** + +1. **Three images** from the asset manifest, each cropped differently: + + - **Image A**: `benchmark/assets/mirrored/cityscape.png` + - Size on slide: 10cm × 8cm, position (1.5cm, 2cm) + - Crop: remove top 15% and bottom 10% of original image + - No shape mask + + - **Image B**: `benchmark/assets/mirrored/cityscape.png` (same image, different crop) + - Size on slide: 8cm × 8cm, position (13cm, 2cm) + - Crop: remove left 30% of original image + - Apply **circle crop mask** (crop to ellipse shape) + + - **Image C**: `benchmark/assets/mirrored/texture-pattern.png` + - Size on slide: 10cm × 8cm, position (22.5cm, 2cm) + - Crop: remove right 25% of original image + - Apply **rounded rectangle crop mask** with 1cm corner radius + +2. **Caption text boxes** below each image: + - "Full panorama crop" / "Circle-masked detail" / "Rounded corner crop" + - Liberation Sans 12pt Italic `#F5F3EE`, centered under each image + +3. **Overlapping layer test** — place a semi-transparent rectangle OVER Image B: + - Size: 6cm × 6cm + - Position: centered on Image B + - Fill: `#1B2A4A` at 50% opacity + - Text: "PREVIEW" in Carlito 24pt Bold `#FFFFFF`, centered + - This rectangle must be ABOVE Image B in z-order + +4. **Title**: "Image Handling" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Tests different crop rectangles on the same image +- Tests crop-to-shape (circle, rounded rectangle) +- Tests z-order with semi-transparent overlay on an image +- Tests that images come from the approved asset manifest (hash verification) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-08.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-08.md new file mode 100644 index 0000000..666a808 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-08.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 08: Overlap, Shadow, and Transparency + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**What to build:** + +1. **Five overlapping "card" shapes** arranged in a cascading stack: + + All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm. + + | Card | Position | Fill | Opacity | Shadow | + |------|----------|------|---------|--------| + | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes | + | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes | + | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes | + | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes | + | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes | + + **Shadow on all cards**: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm. + + Each card contains centered text: + - Card 1: "Layer 1" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 2: "Layer 2" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 3: "Layer 3" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 4: "Layer 4" in Liberation Sans 20pt Bold `#1B2A4A` + - Card 5: "Layer 5" in Liberation Sans 20pt Bold `#1B2A4A` + +2. **Z-order** MUST be exactly as listed: Card 1 at bottom, Card 5 on top. + +3. **Group test**: Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other. + +4. **Gradient fill shape**: a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right). + +5. **Title**: "Depth & Layering" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Tests precise z-order with 5 overlapping shapes +- Tests transparency at different levels +- Tests shadow parameters on every card +- Tests selective grouping (not all grouped, specific subsets) +- Tests gradient fill + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-09.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-09.md new file mode 100644 index 0000000..6427957 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-09.md @@ -0,0 +1,79 @@ +# AcidSlide v1 — Slide 09: Dense Text Overflow + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**What to build:** + +1. **Title** (placeholder): `API Reference` + +2. **Two narrow text columns** (each 14cm × 14cm, side by side): + + **Left column** — text box with NO auto-fit (text should clip if it overflows): + - AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF) + - Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned): + ``` + GET /api/v1/submissions + Authorization: Bearer YOUR_TOKEN_HERE + Content-Type: application/json + + Query Parameters: + model_id string required Filter by model + tier integer optional 1, 2, or 3 + status string optional queued|grading|completed + limit integer optional Default: 20, max: 100 + offset integer optional Default: 0 + + Response 200: + ( + "submissions": [ + ( + "id": "sub_abc123", + "model_id": "gpt-4o", + "tier": 3, + "status": "completed", + "fidelity_score": 0.847, + "created_at": "2025-01-15T10:30:00Z" + ) + ], + "total": 142, + "has_more": true + ) + ``` + + Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Preserve all other characters. + + **Right column** — text box WITH auto-shrink enabled: + - AutoFit: Shrink text on overflow = ON + - Same text content as left column but with this additional block appended: + ``` + + Error Responses: + 401 Unauthorized - Invalid or expired token + 403 Forbidden - Rate limit exceeded + 404 Not Found - Submission not found + 422 Unprocessable - Invalid parameters + 500 Internal Server Error - Contact support + + Rate Limits: + Free tier: 10 req/min, 100 req/hour + Pro tier: 60 req/min, 1000 req/hour + Enterprise: Custom + ``` + +3. **Column labels** above each: + - "Fixed Size (clips)" over left column — Liberation Sans 11pt Bold `#E8634A` + - "Auto-Shrink (fits)" over right column — Liberation Sans 11pt Bold `#2AACB8` + +4. **Line spacing**: exactly 1.15× throughout both columns. + +**Why this slide is hard for AI:** +- Tests autofit behavior (one column clips, one shrinks) +- Tests monospaced text with exact indentation +- Tests dense text layout with no autofit tricks +- Tests line spacing precision +- Tests that text content is preserved exactly (including whitespace) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-10.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-10.md new file mode 100644 index 0000000..0834d2b --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-10.md @@ -0,0 +1,59 @@ +# AcidSlide v1 — Slide 10: Connector and Alignment Diagram + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**What to build:** + +1. **Architecture diagram** using ONLY built-in shapes and connectors: + + **Boxes** (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm): + + | Box | Label | Position | Fill | + |-----|-------|----------|------| + | Client | "Client App" | (2cm, 3cm) | `#2AACB8` | + | API Gateway | "API Gateway" | (14cm, 3cm) | `#1B2A4A` | + | Auth | "Auth Service" | (8cm, 9cm) | `#E8634A` | + | Grader | "Grader" | (20cm, 9cm) | `#E8634A` | + | Queue | "Job Queue" | (14cm, 9cm) | `#D4A843` | + | Storage | "Object Store" | (14cm, 15cm) | `#1B2A4A` | + | DB | "PostgreSQL" | (6cm, 15cm) | `#1B2A4A` | + | LB | "Leaderboard" | (22cm, 15cm) | `#2AACB8` | + + No pair of architecture boxes overlaps. + + All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered. + +2. **Connectors** — use native connectors (Insert → Connector in LibreOffice), NOT plain lines: + - Client → API Gateway (straight connector, arrow at end) + - API Gateway → Auth (elbow connector, arrow at end) + - API Gateway → Queue (straight connector, arrow at end) + - Queue → Grader (straight connector, arrow at end) + - Grader → Storage (straight connector, arrow at end) + - Storage → DB (straight connector, arrow at end) + - Storage → LB (straight connector, arrow at end) + + All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end. + +3. **Labels on connectors** — small text boxes positioned near each connector: + - Client→Gateway: "HTTPS" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Auth: "JWT verify" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Queue: "Enqueue" (Liberation Sans 10pt `#FFFFFF`) + +4. **Nested grouping**: + - Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text "Processing Layer" above) + - Group 2: Storage + DB + LB boxes (label with "Persistence Layer") + - Group 3: Group 1 + Group 2 (the "Backend" super-group) + +5. **Title**: "System Architecture" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Tests native connectors (not plain lines) +- Tests nested grouping (groups inside groups) +- Tests precise alignment grid +- Tests connector routing between boxes +- Tests label positioning relative to connectors + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-11.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-11.md new file mode 100644 index 0000000..072f38c --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-11.md @@ -0,0 +1,40 @@ +# AcidSlide v1 — Slide 11: Theme vs Local Override + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**What to build:** + +1. **Title** (placeholder): `Brand Colors` + +2. **Six color swatches in two rows of three** — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row. + + **Top row — inherited from theme/master** (these must use theme color references, NOT hardcoded hex): + - Swatch 1: Theme Primary color + - Swatch 2: Theme Secondary color + - Swatch 3: Theme Accent 1 color + + Below each: text with the role name ("Primary", "Secondary", "Accent 1") in Liberation Sans 12pt `#F5F3EE` + + **Bottom row — locally overridden** (these must use explicit RGB hex, NOT theme references): + - Swatch 4: `#FF6B35` (explicit override — different from theme) + - Swatch 5: `#7B2D8E` (explicit override) + - Swatch 6: `#3D9970` (explicit override) + + Below each: text "Override" in Liberation Sans 12pt, same explicit color as the swatch + +3. **The critical test**: if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML. + +4. **Explanatory text box** at bottom: + - "Top row uses theme color references. Bottom row uses explicit RGB values." + - "Changing the theme will update the top row but not the bottom row." + - Liberation Sans 13pt `#F5F3EE` + +**Why this slide is hard for AI:** +- Tests theme color reference vs. explicit RGB in the OOXML +- Tests that AI understands the semantic difference between inheriting and overriding +- The slide looks similar visually but the XML structure must be different + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-12.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-12.md new file mode 100644 index 0000000..d359df8 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-12.md @@ -0,0 +1,42 @@ +# AcidSlide v1 — Slide 12: Native Field Slide + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**What to build:** + +1. **Title** (placeholder): `Document Fields` + +2. **Three field demonstrations** — each in its own text box: + + **Field 1 — Slide Number**: + - Text box: "Current slide: " followed by an **inserted slide number field** (LibreOffice: Insert → Field → Page Number) + - Do NOT type the number manually. It MUST be a live field. + - Liberation Sans 18pt `#FFFFFF` + + **Field 2 — Date/Time**: + - `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed exactly as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`. + + **Field 3 — Footer**: + - The slide footer (from View → Header and Footer) should contain: "AcidSlide Benchmark v1" + - This must be enabled via the master's footer placeholder + +3. **Explanatory labels** next to each: + - "← Live slide number field (not static text)" + - "← Fixed date/time field" + - "← Footer from master placeholder" + - Liberation Sans 12pt Italic `#2AACB8` + +4. **A static text comparison** — a text box that says "Slide 12" in the same font/size as Field 1, to highlight the difference between static text and a live field. + +**Why this slide is hard for AI:** +- Tests native field insertion (not static text that looks like a field) +- Tests date/time field (the grader pins the datetime) +- Tests footer field from master +- The grader verifies field type in OOXML, not just rendered text + +--- + +## Slides 13-20 (Level 3) — Brief Specifications diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-13.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-13.md new file mode 100644 index 0000000..d75b868 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-13.md @@ -0,0 +1,14 @@ +# AcidSlide v1 — Slide 13: Composite Stress + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations. + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm). +- Add one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Use six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend. +- Add one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`. +- Insert `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Use only asset ID `cityscape` from the manifest. +- Add the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction. +- Add three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-14.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-14.md new file mode 100644 index 0000000..828c2a3 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-14.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 14: RTL-Heavy Comparison + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., "The الذكاء الاصطناعي revolution"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned. + +## Explicit v1 constraints + +- Use the **Two-Column** layout with title `RTL Systems Review`. +- The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`. +- The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.` +- Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them. +- Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-15.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-15.md new file mode 100644 index 0000000..bac5599 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-15.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 15: Rotated Text + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Tests exact anchor points for rotated elements. + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Rotation Atlas`. +- Create five text boxes labeled exactly `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`. +- Apply rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation. +- Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Keep text editable and store rotations in native OOXML transforms. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-16.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-16.md new file mode 100644 index 0000000..db2e7c1 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-16.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 16: Intentional Off-Canvas Bleed + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors. + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Beyond the Frame`. +- Place a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm). +- Add on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.` +- Preserve negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-17.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-17.md new file mode 100644 index 0000000..2d73e48 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-17.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 17: Deep Grouping + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +3 levels of nested groups. Inner groups contain exactly 3 shapes each. Middle groups contain exactly 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level. + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Nested Systems`. +- Build one outer group containing three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total). +- Use native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`. +- Within every inner group, z-order is circle below rounded rectangle below label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-18.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-18.md new file mode 100644 index 0000000..5680e8a --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-18.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 18: Multi-Column Editorial + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column. + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Three Cities / 三つの都市`. +- Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote. +- Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media. +- Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。` +- Apply the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Use 0.9cm gutters consistently. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-19.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-19.md new file mode 100644 index 0000000..e9b873a --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-19.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 19: Repetition and Consistency + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights exactly. Tests deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs). + +## Explicit v1 constraints + +- Use the **Content Slide** layout with title `Design System Audit`. +- Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must use the deck-level tokens exactly: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule. +- Create two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs. +- Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes. diff --git a/acidslide-v1/benchmark/prompts/variants/canonical/slide-20.md b/acidslide-v1/benchmark/prompts/variants/canonical/slide-20.md new file mode 100644 index 0000000..25eeef7 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/canonical/slide-20.md @@ -0,0 +1,15 @@ +# AcidSlide v1 — Slide 20: Final Torture Slide + +The natural-language requirements below are the primary directive. Use the reference image only as supplementary visual guidance. + +Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide. + +--- + +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `AcidSlide Synthesis`. +- Add one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`. +- Add one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`. +- Insert `hero-abstract.png` with a 20% left crop. Add Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP. +- Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-01.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-01.md new file mode 100644 index 0000000..be8e1ff --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-01.md @@ -0,0 +1,43 @@ +# AcidSlide v1 — Slide 01: Cover / Title Stress Test (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Title Slide" (from master) +**Tier:** Level 1 + +**Required construction:** + +1. Select the "Title Slide" layout — the title and subtitle must originate from the layout placeholders, not freestanding text boxes. + +2. **Title text** (in the title placeholder): + ``` + AcidSlide v1 + ``` + +3. **Subtitle text** (in the subtitle placeholder): + ``` + Benchmark for Slide Generation Fidelity + ``` + +4. **Hero image**: Position `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Ensure that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is precisely the slide's right edge. + - The image should overlap with decorative shapes (see under) + +5. **Decorative shapes** (3 overlapping rounded rectangles): + - Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline + - Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline + - Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline + +6. **Z-order** (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text + +7. **Shadow**: Set a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm. + +8. **Slide number**: must come from the master's slide number placeholder (do NOT type "1" manually). + +**Why this slide is hard for AI:** +- Evaluates placeholder usage (not manual text boxes) +- Evaluates precise crop rectangle on an image +- Evaluates z-order with overlapping semi-transparent shapes +- Evaluates shadow parameters +- Evaluates master-driven footer/slide number inheritance + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-02.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-02.md new file mode 100644 index 0000000..b92d601 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-02.md @@ -0,0 +1,48 @@ +# AcidSlide v1 — Slide 02: Dense Agenda with Layout Semantics (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Required construction:** + +1. Select the "Content Slide" layout. Title and body must remain in the layout placeholders. + +2. **Title** (placeholder): `Agenda` + +3. **Body** (placeholder) — a bulleted list with specific formatting: + ``` + • Opening Remarks + ◦ Welcome and introductions + ◦ Safety briefing + • Technical Deep Dive + ◦ Architecture overview + ◦ Performance benchmarks + ◦ Security audit results + • Breakout Sessions + ◦ Track A: Infrastructure + ◦ Track B: Applications + • Closing & Next Steps + ``` + + - Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A` + - Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE` + - Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm + - Line spacing: 1.2× for Level 1, 1.0× for Level 2 + - Paragraph spacing: 6pt after each Level 1 item + + Employ native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs. + +4. **Grouped icon-text rows**: Construct three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored. + - The three time labels, from top to bottom, are "09:00", "11:30", and "14:00" in Liberation Sans 14pt Bold `#FFFFFF`. + - Each circle is filled with `#2AACB8`. + +**Why this slide is hard for AI:** +- Evaluates bullet hierarchy (indentation, different bullet characters) +- Evaluates paragraph-level formatting (spacing, indent) +- Evaluates object grouping (the time column must be one group) +- Evaluates placeholder usage for title and body +- Evaluates alignment precision + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-03.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-03.md new file mode 100644 index 0000000..71fa4a1 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-03.md @@ -0,0 +1,56 @@ +# AcidSlide v1 — Slide 03: Native Table Stress Test (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 1 + +**Required construction:** + +1. **Title text box** (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders): + - Text: `Performance Metrics` + - Font: Carlito 36pt Bold, `#FFFFFF` + - Position: x=1.5cm, y=0.8cm + +2. **Native table** — this must remain a real LibreOffice Impress table, not shapes pretending to be a table: + - Position: x=1.5cm, y=3cm + - Size: 30cm × 12cm + - Rows: 7 (1 header + 6 data) + - Columns: 5 + + | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target | + |--------|---------|---------|---------|--------| + | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms | + | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms | + | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps | + | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% | + | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% | + | Cache Hit | 72% | 78% | 84% | ≥80% | + + **Table styling:** + - Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered + - Data rows: alternating `#0F1923` and `#161F2E` + - Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for "Metric", centered for all others + - Cell padding: 0.3cm on all sides + - Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` under header row + - Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold. + - Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓) + +3. **Annotation callout** — a rounded rectangle with text, placed next to the table: + - Position: x=24cm, y=15.5cm + - Size: 8cm × 2.5cm + - Fill: `#E8634A` + - Corner radius: 0.3cm + - Text: "Throughput target\nmissed by 5.5%" in Liberation Sans 12pt Bold `#FFFFFF`, centered + - A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained. + +4. **Paragraph indent**: the Metric-column paragraphs is required to use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required. + +**Why this slide is hard for AI:** +- Evaluates native table creation (not shapes) +- Evaluates cell-level formatting (conditional colors) +- Evaluates table borders (mixed weights) +- Evaluates tab stops and paragraph indentation inside table cells +- Evaluates annotation positioning relative to table cells + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-04.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-04.md new file mode 100644 index 0000000..f188311 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-04.md @@ -0,0 +1,71 @@ +# AcidSlide v1 — Slide 04: Native Chart Stress Test (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Required construction:** + +1. **Title** (placeholder): `Revenue Growth` + +2. **Native chart** — must remain a real LibreOffice Impress chart, not shapes/images: + - Chart type: **Clustered bar chart** (horizontal bars) + - Position: x=1.5cm, y=3cm + - Size: 20cm × 14cm + + **Chart data:** + + | Region | 2023 Revenue ($M) | 2024 Revenue ($M) | + |--------|-------------------|--------------------| + | North America | 42.3 | 51.8 | + | Europe | 28.7 | 35.2 | + | Asia Pacific | 19.4 | 31.6 | + | Latin America | 8.1 | 12.4 | + | Middle East & Africa | 3.9 | 7.2 | + + **Chart formatting:** + - 2023 bars: `#1B2A4A` (navy) + - 2024 bars: `#E8634A` (coral) + - Chart title: "Annual Revenue by Region" in Carlito 16pt Bold + - X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`. + - Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`. + - Legend: bottom of chart, Liberation Sans 11pt + - Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt. + - No chart border + - Background: transparent (slide background shows through) + +3. **Callout shapes** — two overlaid callout annotations: + + - Callout 1: placed over the "Asia Pacific 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#2AACB8` + - Text: "+62.9% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + + - Callout 2: placed over the "Middle East & Africa 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#D4A843` + - Text: "+84.6% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + +4. **Supporting text block** to the right of the chart: + - Position: x=23cm, y=4cm + - Width: 9cm + - Text (Liberation Sans 14pt, `#F5F3EE`): + ``` + Key Takeaways: + + ▸ Total revenue up 38.2% YoY + ▸ APAC fastest-growing region + ▸ All regions exceeded targets + ``` + +**Why this slide is hard for AI:** +- Evaluates native chart creation with specific chart type +- Evaluates chart formatting (colors, labels, gridlines, legend) +- Evaluates chart data accuracy +- Evaluates overlay shapes on top of chart +- Evaluates connector arrows between callouts and chart elements + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-05.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-05.md new file mode 100644 index 0000000..d93fdd4 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-05.md @@ -0,0 +1,50 @@ +# AcidSlide v1 — Slide 05: Master Reuse Enforcement (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Required construction:** + +This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied. + +1. **Title** (placeholder): `Our Team` + +2. **Body content** — three team member cards arranged horizontally: + + Each card is a group that includes: + - A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8` + - Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text "Photo" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos + - Name: Carlito 18pt Bold `#FFFFFF`, centered + - Title: Liberation Sans 14pt `#E8634A`, centered + - Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines + + **Card 1:** + - Name: "Sarah Chen" + - Title: "Chief Architect" + - Description: "15 years building distributed systems at scale" + + **Card 2:** + - Name: "Marcus Rivera" + - Title: "Head of Design" + - Description: "Formerly at Apple, obsessed with pixel-perfect interfaces" + + **Card 3:** + - Name: "Yuki Tanaka" + - Title: "ML Engineering Lead" + - Description: "PhD in NLP, built the model serving infrastructure" + + Cards placed at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide. + +3. **Non-negotiable requirement**: The bottom footer line, "ACIDSLIDE" text, and slide number must originate from the master. Never manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited. + +4. **The accent bar** on the left edge must also come from the "Content Slide" layout, not a manually placed shape. + +**Why this slide is hard for AI:** +- Evaluates that repeated elements (footer, line, text, slide number) come from master inheritance +- Evaluates grouped objects (each card is a group) +- Evaluates precise horizontal distribution of equal-sized elements +- Evaluates placeholder text formatting within groups + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-06.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-06.md new file mode 100644 index 0000000..790d446 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-06.md @@ -0,0 +1,65 @@ +# AcidSlide v1 — Slide 06: Multilingual Editorial (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 2 + +**Required construction:** + +1. **Three text columns** side by side: + + **Column 1 — English** (left third): + - Title: "Global Perspectives" in Carlito 24pt Bold `#FFFFFF` + - Body (Liberation Sans 14pt `#F5F3EE`, left-aligned): + ``` + The rapid advancement of language models + has transformed how organizations approach + document generation. From financial reports + to marketing materials, AI-driven content + creation is reshaping every industry. + ``` + + **Column 2 — Arabic RTL** (center third): + - Title: "وجهات نظر عالمية" in Noto Sans Arabic 24pt Bold `#FFFFFF` + - Body (Noto Sans Arabic 14pt `#F5F3EE`, **RIGHT-to-left aligned**): + ``` + لقد أدى التقدم السريع في نماذج اللغة إلى تحويل + كيفية تعامل المؤسسات مع إنشاء المستندات. من + التقارير المالية إلى المواد التسويقية، يعيد إنشاء + المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة. + ``` + - **CRITICAL**: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL. + + **Column 3 — Japanese** (right third): + - Title: "グローバルな視点" in Noto Sans CJK JP 24pt Bold `#FFFFFF` + - Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned): + ``` + 言語モデルの急速な進歩により、組織がドキュメント生成に + 取り組む方法が変革されました。財務報告からマーケティング + 資料まで、AI主導のコンテンツ作成はあらゆる産業を + 再形成しています。 + ``` + +2. **Decorative separator lines** between columns: + - Vertical lines at x=11.2cm and x=22.5cm + - Height: from y=3cm to y=16cm + - Style: 1pt, `#2AACB8`, 50% opacity + +3. **Callout box** overlapping the Arabic and Japanese columns: + - Position: x=15cm, y=13cm + - Size: 12cm × 4cm + - Fill: `#E8634A` at 90% opacity + - Text: "AI-generated slides must handle RTL text,\nCJK line breaking, and mixed scripts correctly." + - Font: Liberation Sans 13pt Bold `#FFFFFF`, centered + - Corner radius: 0.3cm + - This callout should overlap both the Arabic and Japanese columns + +**Why this slide is hard for AI:** +- Evaluates correct RTL paragraph direction (not just alignment) +- Evaluates CJK text rendering and line breaking +- Evaluates correct font assignment per script +- Evaluates overlap between callout and text columns +- Evaluates Unicode text preservation (exact characters must match) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-07.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-07.md new file mode 100644 index 0000000..d7d9d14 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-07.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 07: Image Crop and Mask (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Required construction:** + +1. **Three images** from the asset manifest, each cropped differently: + + - **Image A**: `benchmark/assets/mirrored/cityscape.png` + - Size on slide: 10cm × 8cm, position (1.5cm, 2cm) + - Crop: remove top 15% and bottom 10% of original image + - No shape mask + + - **Image B**: `benchmark/assets/mirrored/cityscape.png` (same image, different crop) + - Size on slide: 8cm × 8cm, position (13cm, 2cm) + - Crop: remove left 30% of original image + - Set **circle crop mask** (crop to ellipse shape) + + - **Image C**: `benchmark/assets/mirrored/texture-pattern.png` + - Size on slide: 10cm × 8cm, position (22.5cm, 2cm) + - Crop: remove right 25% of original image + - Set **rounded rectangle crop mask** with 1cm corner radius + +2. **Caption text boxes** under each image: + - "Full panorama crop" / "Circle-masked detail" / "Rounded corner crop" + - Liberation Sans 12pt Italic `#F5F3EE`, centered under each image + +3. **Overlapping layer test** — place a semi-transparent rectangle OVER Image B: + - Size: 6cm × 6cm + - Position: centered on Image B + - Fill: `#1B2A4A` at 50% opacity + - Text: "PREVIEW" in Carlito 24pt Bold `#FFFFFF`, centered + - This rectangle must be ABOVE Image B in z-order + +4. **Title**: "Image Handling" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Evaluates different crop rectangles on the same image +- Evaluates crop-to-shape (circle, rounded rectangle) +- Evaluates z-order with semi-transparent overlay on an image +- Evaluates that images come from the approved asset manifest (hash verification) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-08.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-08.md new file mode 100644 index 0000000..80e5696 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-08.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 08: Overlap, Shadow, and Transparency (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Required construction:** + +1. **Five overlapping "card" shapes** arranged in a cascading stack: + + All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm. + + | Card | Position | Fill | Opacity | Shadow | + |------|----------|------|---------|--------| + | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes | + | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes | + | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes | + | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes | + | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes | + + **Shadow on all cards**: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm. + + Each card contains centered text: + - Card 1: "Layer 1" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 2: "Layer 2" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 3: "Layer 3" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 4: "Layer 4" in Liberation Sans 20pt Bold `#1B2A4A` + - Card 5: "Layer 5" in Liberation Sans 20pt Bold `#1B2A4A` + +2. **Z-order** must remain precisely as listed: Card 1 at bottom, Card 5 on top. + +3. **Group test**: Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other. + +4. **Gradient fill shape**: a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right). + +5. **Title**: "Depth & Layering" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Evaluates precise z-order with 5 overlapping shapes +- Evaluates transparency at different levels +- Evaluates shadow parameters on every card +- Evaluates selective grouping (not all grouped, specific subsets) +- Evaluates gradient fill + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-09.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-09.md new file mode 100644 index 0000000..6a02bf9 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-09.md @@ -0,0 +1,79 @@ +# AcidSlide v1 — Slide 09: Dense Text Overflow (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Required construction:** + +1. **Title** (placeholder): `API Reference` + +2. **Two narrow text columns** (each 14cm × 14cm, side by side): + + **Left column** — text box with NO auto-fit (text should clip if it overflows): + - AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF) + - Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned): + ``` + GET /api/v1/submissions + Authorization: Bearer YOUR_TOKEN_HERE + Content-Type: application/json + + Query Parameters: + model_id string required Filter by model + tier integer optional 1, 2, or 3 + status string optional queued|grading|completed + limit integer optional Default: 20, max: 100 + offset integer optional Default: 0 + + Response 200: + ( + "submissions": [ + ( + "id": "sub_abc123", + "model_id": "gpt-4o", + "tier": 3, + "status": "completed", + "fidelity_score": 0.847, + "created_at": "2025-01-15T10:30:00Z" + ) + ], + "total": 142, + "has_more": true + ) + ``` + + Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Retain all other characters. + + **Right column** — text box WITH auto-shrink enabled: + - AutoFit: Shrink text on overflow = ON + - Same text content as left column but with this additional block appended: + ``` + + Error Responses: + 401 Unauthorized - Invalid or expired token + 403 Forbidden - Rate limit exceeded + 404 Not Found - Submission not found + 422 Unprocessable - Invalid parameters + 500 Internal Server Error - Contact support + + Rate Limits: + Free tier: 10 req/min, 100 req/hour + Pro tier: 60 req/min, 1000 req/hour + Enterprise: Custom + ``` + +3. **Column labels** over each: + - "Fixed Size (clips)" over left column — Liberation Sans 11pt Bold `#E8634A` + - "Auto-Shrink (fits)" over right column — Liberation Sans 11pt Bold `#2AACB8` + +4. **Line spacing**: precisely 1.15× throughout both columns. + +**Why this slide is hard for AI:** +- Evaluates autofit behavior (one column clips, one shrinks) +- Evaluates monospaced text with exact indentation +- Evaluates dense text layout with no autofit tricks +- Evaluates line spacing precision +- Evaluates that text content is preserved precisely (including whitespace) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-10.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-10.md new file mode 100644 index 0000000..3f9d8f1 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-10.md @@ -0,0 +1,59 @@ +# AcidSlide v1 — Slide 10: Connector and Alignment Diagram (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Required construction:** + +1. **Architecture diagram** using ONLY built-in shapes and connectors: + + **Boxes** (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm): + + | Box | Label | Position | Fill | + |-----|-------|----------|------| + | Client | "Client App" | (2cm, 3cm) | `#2AACB8` | + | API Gateway | "API Gateway" | (14cm, 3cm) | `#1B2A4A` | + | Auth | "Auth Service" | (8cm, 9cm) | `#E8634A` | + | Grader | "Grader" | (20cm, 9cm) | `#E8634A` | + | Queue | "Job Queue" | (14cm, 9cm) | `#D4A843` | + | Storage | "Object Store" | (14cm, 15cm) | `#1B2A4A` | + | DB | "PostgreSQL" | (6cm, 15cm) | `#1B2A4A` | + | LB | "Leaderboard" | (22cm, 15cm) | `#2AACB8` | + + No pair of architecture boxes overlaps. + + All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered. + +2. **Connectors** — use native connectors (Position → Connector in LibreOffice), NOT plain lines: + - Client → API Gateway (straight connector, arrow at end) + - API Gateway → Auth (elbow connector, arrow at end) + - API Gateway → Queue (straight connector, arrow at end) + - Queue → Grader (straight connector, arrow at end) + - Grader → Storage (straight connector, arrow at end) + - Storage → DB (straight connector, arrow at end) + - Storage → LB (straight connector, arrow at end) + + All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end. + +3. **Labels on connectors** — small text boxes placed near each connector: + - Client→Gateway: "HTTPS" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Auth: "JWT verify" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Queue: "Enqueue" (Liberation Sans 10pt `#FFFFFF`) + +4. **Nested grouping**: + - Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text "Processing Layer" over) + - Group 2: Storage + DB + LB boxes (label with "Persistence Layer") + - Group 3: Group 1 + Group 2 (the "Backend" super-group) + +5. **Title**: "System Architecture" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Evaluates native connectors (not plain lines) +- Evaluates nested grouping (groups inside groups) +- Evaluates precise alignment grid +- Evaluates connector routing between boxes +- Evaluates label positioning relative to connectors + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-11.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-11.md new file mode 100644 index 0000000..a763fc7 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-11.md @@ -0,0 +1,40 @@ +# AcidSlide v1 — Slide 11: Theme vs Local Override (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Required construction:** + +1. **Title** (placeholder): `Brand Colors` + +2. **Six color swatches in two rows of three** — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row. + + **Top row — inherited from theme/master** (these is required to use theme color references, NOT hardcoded hex): + - Swatch 1: Theme Primary color + - Swatch 2: Theme Secondary color + - Swatch 3: Theme Accent 1 color + + Below each: text with the role name ("Primary", "Secondary", "Accent 1") in Liberation Sans 12pt `#F5F3EE` + + **Bottom row — locally overridden** (these is required to use explicit RGB hex, NOT theme references): + - Swatch 4: `#FF6B35` (explicit override — different from theme) + - Swatch 5: `#7B2D8E` (explicit override) + - Swatch 6: `#3D9970` (explicit override) + + Below each: text "Override" in Liberation Sans 12pt, same explicit color as the swatch + +3. **The critical test**: if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML. + +4. **Explanatory text box** at bottom: + - "Top row uses theme color references. Bottom row uses explicit RGB values." + - "Changing the theme will update the top row but not the bottom row." + - Liberation Sans 13pt `#F5F3EE` + +**Why this slide is hard for AI:** +- Evaluates theme color reference vs. explicit RGB in the OOXML +- Evaluates that AI understands the semantic difference between inheriting and overriding +- The slide looks similar visually but the XML structure must be different + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-12.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-12.md new file mode 100644 index 0000000..f3f379b --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-12.md @@ -0,0 +1,42 @@ +# AcidSlide v1 — Slide 12: Native Field Slide (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Required construction:** + +1. **Title** (placeholder): `Document Fields` + +2. **Three field demonstrations** — each in its own text box: + + **Field 1 — Slide Number**: + - Text box: "Current slide: " followed by an **inserted slide number field** (LibreOffice: Position → Field → Page Number) + - Never type the number manually. It must remain a live field. + - Liberation Sans 18pt `#FFFFFF` + + **Field 2 — Date/Time**: + - `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed precisely as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`. + + **Field 3 — Footer**: + - The slide footer (from View → Header and Footer) should contain: "AcidSlide Benchmark v1" + - This must be enabled via the master's footer placeholder + +3. **Explanatory labels** next to each: + - "← Live slide number field (not static text)" + - "← Fixed date/time field" + - "← Footer from master placeholder" + - Liberation Sans 12pt Italic `#2AACB8` + +4. **A static text comparison** — a text box that says "Slide 12" in the same font/size as Field 1, to highlight the difference between static text and a live field. + +**Why this slide is hard for AI:** +- Evaluates native field insertion (not static text that looks like a field) +- Evaluates date/time field (the grader pins the datetime) +- Evaluates footer field from master +- The grader verifies field type in OOXML, not just rendered text + +--- + +## Slides 13-20 (Level 3) — Brief Specifications diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-13.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-13.md new file mode 100644 index 0000000..1658c6f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-13.md @@ -0,0 +1,14 @@ +# AcidSlide v1 — Slide 13: Composite Stress (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations. + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm). +- Include one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Employ six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend. +- Include one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`. +- Position `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Rely exclusively on asset ID `cityscape` from the manifest. +- Include the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction. +- Include three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-14.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-14.md new file mode 100644 index 0000000..9938c2f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-14.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 14: RTL-Heavy Comparison (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., "The الذكاء الاصطناعي revolution"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned. + +## Mandatory v1 requirements + +- Select the **Two-Column** layout with title `RTL Systems Review`. +- The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`. +- The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.` +- Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them. +- Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-15.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-15.md new file mode 100644 index 0000000..161a4d0 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-15.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 15: Rotated Text (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Evaluates exact anchor points for rotated elements. + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout with title `Rotation Atlas`. +- Construct five text boxes labeled precisely `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`. +- Set rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation. +- Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Ensure text editable and store rotations in native OOXML transforms. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-16.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-16.md new file mode 100644 index 0000000..5aac36f --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-16.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 16: Intentional Off-Canvas Bleed (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors. + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout with title `Beyond the Frame`. +- Position a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm). +- Include on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.` +- Retain negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-17.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-17.md new file mode 100644 index 0000000..f07d220 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-17.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 17: Deep Grouping (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +3 levels of nested groups. Inner groups contain precisely 3 shapes each. Middle groups contain precisely 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level. + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout with title `Nested Systems`. +- Build one outer group that includes three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total). +- Employ native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`. +- Within every inner group, z-order is circle under rounded rectangle under label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-18.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-18.md new file mode 100644 index 0000000..0bbf69b --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-18.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 18: Multi-Column Editorial (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column. + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout with title `Three Cities / 三つの都市`. +- Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote. +- Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media. +- Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。` +- Set the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Employ 0.9cm gutters consistently. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-19.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-19.md new file mode 100644 index 0000000..0c8fb85 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-19.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 19: Repetition and Consistency (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights precisely. Evaluates deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs). + +## Mandatory v1 requirements + +- Select the **Content Slide** layout with title `Design System Audit`. +- Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample is required to use the deck-level tokens precisely: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule. +- Construct two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs. +- Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-20.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-20.md new file mode 100644 index 0000000..a14bfc8 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-a/slide-20.md @@ -0,0 +1,15 @@ +# AcidSlide v1 — Slide 20: Final Torture Slide (alternative wording A) + +The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only. + +Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide. + +--- + +## Mandatory v1 requirements + +- Select the **Blank with Footer** layout with title `AcidSlide Synthesis`. +- Include one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`. +- Include one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`. +- Position `hero-abstract.png` with a 20% left crop. Include Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP. +- Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-01.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-01.md new file mode 100644 index 0000000..4bc206e --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-01.md @@ -0,0 +1,43 @@ +# AcidSlide v1 — Slide 01: Cover / Title Stress Test (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Title Slide" (from master) +**Tier:** Level 1 + +**Acceptance-target composition:** + +1. Adopt the "Title Slide" layout — the title and subtitle must be inherited from the layout placeholders, not freestanding text boxes. + +2. **Title text** (in the title placeholder): + ``` + AcidSlide v1 + ``` + +3. **Subtitle text** (in the subtitle placeholder): + ``` + Benchmark for Slide Generation Fidelity + ``` + +4. **Hero image**: Set `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Maintain that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is with exact precision the slide's right edge. + - The image should overlap with decorative shapes (see beneath) + +5. **Decorative shapes** (3 overlapping rounded rectangles): + - Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline + - Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline + - Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline + +6. **Z-order** (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text + +7. **Shadow**: Assign a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm. + +8. **Slide number**: must come from the master's slide number placeholder (do NOT type "1" manually). + +**Why this slide is hard for AI:** +- Measures placeholder usage (not manual text boxes) +- Measures precise crop rectangle on an image +- Measures z-order with overlapping semi-transparent shapes +- Measures shadow parameters +- Measures master-driven footer/slide number inheritance + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-02.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-02.md new file mode 100644 index 0000000..7ed4a13 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-02.md @@ -0,0 +1,48 @@ +# AcidSlide v1 — Slide 02: Dense Agenda with Layout Semantics (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Acceptance-target composition:** + +1. Adopt the "Content Slide" layout. Title and body must be implemented as in the layout placeholders. + +2. **Title** (placeholder): `Agenda` + +3. **Body** (placeholder) — a bulleted list with specific formatting: + ``` + • Opening Remarks + ◦ Welcome and introductions + ◦ Safety briefing + • Technical Deep Dive + ◦ Architecture overview + ◦ Performance benchmarks + ◦ Security audit results + • Breakout Sessions + ◦ Track A: Infrastructure + ◦ Track B: Applications + • Closing & Next Steps + ``` + + - Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A` + - Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE` + - Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm + - Line spacing: 1.2× for Level 1, 1.0× for Level 2 + - Paragraph spacing: 6pt after each Level 1 item + + Choose native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs. + +4. **Grouped icon-text rows**: Produce three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored. + - The three time labels, from top to bottom, are "09:00", "11:30", and "14:00" in Liberation Sans 14pt Bold `#FFFFFF`. + - Each circle is filled with `#2AACB8`. + +**Why this slide is hard for AI:** +- Measures bullet hierarchy (indentation, different bullet characters) +- Measures paragraph-level formatting (spacing, indent) +- Measures object grouping (the time column must be one group) +- Measures placeholder usage for title and body +- Measures alignment precision + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-03.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-03.md new file mode 100644 index 0000000..a4b80a3 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-03.md @@ -0,0 +1,56 @@ +# AcidSlide v1 — Slide 03: Native Table Stress Test (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 1 + +**Acceptance-target composition:** + +1. **Title text box** (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders): + - Text: `Performance Metrics` + - Font: Carlito 36pt Bold, `#FFFFFF` + - Position: x=1.5cm, y=0.8cm + +2. **Native table** — this must be implemented as a real LibreOffice Impress table, not shapes pretending to be a table: + - Position: x=1.5cm, y=3cm + - Size: 30cm × 12cm + - Rows: 7 (1 header + 6 data) + - Columns: 5 + + | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target | + |--------|---------|---------|---------|--------| + | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms | + | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms | + | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps | + | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% | + | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% | + | Cache Hit | 72% | 78% | 84% | ≥80% | + + **Table styling:** + - Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered + - Data rows: alternating `#0F1923` and `#161F2E` + - Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for "Metric", centered for all others + - Cell padding: 0.3cm on all sides + - Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` beneath header row + - Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold. + - Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓) + +3. **Annotation callout** — a rounded rectangle with text, located next to the table: + - Position: x=24cm, y=15.5cm + - Size: 8cm × 2.5cm + - Fill: `#E8634A` + - Corner radius: 0.3cm + - Text: "Throughput target\nmissed by 5.5%" in Liberation Sans 12pt Bold `#FFFFFF`, centered + - A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained. + +4. **Paragraph indent**: the Metric-column paragraphs must employ a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required. + +**Why this slide is hard for AI:** +- Measures native table creation (not shapes) +- Measures cell-level formatting (conditional colors) +- Measures table borders (mixed weights) +- Measures tab stops and paragraph indentation inside table cells +- Measures annotation positioning relative to table cells + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-04.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-04.md new file mode 100644 index 0000000..487a5f4 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-04.md @@ -0,0 +1,71 @@ +# AcidSlide v1 — Slide 04: Native Chart Stress Test (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Acceptance-target composition:** + +1. **Title** (placeholder): `Revenue Growth` + +2. **Native chart** — must be implemented as a real LibreOffice Impress chart, not shapes/images: + - Chart type: **Clustered bar chart** (horizontal bars) + - Position: x=1.5cm, y=3cm + - Size: 20cm × 14cm + + **Chart data:** + + | Region | 2023 Revenue ($M) | 2024 Revenue ($M) | + |--------|-------------------|--------------------| + | North America | 42.3 | 51.8 | + | Europe | 28.7 | 35.2 | + | Asia Pacific | 19.4 | 31.6 | + | Latin America | 8.1 | 12.4 | + | Middle East & Africa | 3.9 | 7.2 | + + **Chart formatting:** + - 2023 bars: `#1B2A4A` (navy) + - 2024 bars: `#E8634A` (coral) + - Chart title: "Annual Revenue by Region" in Carlito 16pt Bold + - X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`. + - Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`. + - Legend: bottom of chart, Liberation Sans 11pt + - Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt. + - No chart border + - Background: transparent (slide background shows through) + +3. **Callout shapes** — two overlaid callout annotations: + + - Callout 1: located over the "Asia Pacific 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#2AACB8` + - Text: "+62.9% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + + - Callout 2: located over the "Middle East & Africa 2024" bar + - Rounded rectangle, 5cm × 2cm + - Fill: `#D4A843` + - Text: "+84.6% YoY" in Liberation Sans 14pt Bold `#FFFFFF` + - Arrow connector pointing from callout to the bar + +4. **Supporting text block** to the right of the chart: + - Position: x=23cm, y=4cm + - Width: 9cm + - Text (Liberation Sans 14pt, `#F5F3EE`): + ``` + Key Takeaways: + + ▸ Total revenue up 38.2% YoY + ▸ APAC fastest-growing region + ▸ All regions exceeded targets + ``` + +**Why this slide is hard for AI:** +- Measures native chart creation with specific chart type +- Measures chart formatting (colors, labels, gridlines, legend) +- Measures chart data accuracy +- Measures overlay shapes on top of chart +- Measures connector arrows between callouts and chart elements + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-05.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-05.md new file mode 100644 index 0000000..05b78cc --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-05.md @@ -0,0 +1,50 @@ +# AcidSlide v1 — Slide 05: Master Reuse Enforcement (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" (from master) +**Tier:** Level 1 + +**Acceptance-target composition:** + +This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied. + +1. **Title** (placeholder): `Our Team` + +2. **Body content** — three team member cards arranged horizontally: + + Each card is a group composed of: + - A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8` + - Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text "Photo" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos + - Name: Carlito 18pt Bold `#FFFFFF`, centered + - Title: Liberation Sans 14pt `#E8634A`, centered + - Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines + + **Card 1:** + - Name: "Sarah Chen" + - Title: "Chief Architect" + - Description: "15 years building distributed systems at scale" + + **Card 2:** + - Name: "Marcus Rivera" + - Title: "Head of Design" + - Description: "Formerly at Apple, obsessed with pixel-perfect interfaces" + + **Card 3:** + - Name: "Yuki Tanaka" + - Title: "ML Engineering Lead" + - Description: "PhD in NLP, built the model serving infrastructure" + + Cards located at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide. + +3. **Required invariant**: The bottom footer line, "ACIDSLIDE" text, and slide number must be inherited from the master. Do not ever manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited. + +4. **The accent bar** on the left edge must also come from the "Content Slide" layout, not a manually placed shape. + +**Why this slide is hard for AI:** +- Measures that repeated elements (footer, line, text, slide number) come from master inheritance +- Measures grouped objects (each card is a group) +- Measures precise horizontal distribution of equal-sized elements +- Measures placeholder text formatting within groups + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-06.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-06.md new file mode 100644 index 0000000..cd5e5e4 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-06.md @@ -0,0 +1,65 @@ +# AcidSlide v1 — Slide 06: Multilingual Editorial (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Blank with Footer" (from master) +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Three text columns** side by side: + + **Column 1 — English** (left third): + - Title: "Global Perspectives" in Carlito 24pt Bold `#FFFFFF` + - Body (Liberation Sans 14pt `#F5F3EE`, left-aligned): + ``` + The rapid advancement of language models + has transformed how organizations approach + document generation. From financial reports + to marketing materials, AI-driven content + creation is reshaping every industry. + ``` + + **Column 2 — Arabic RTL** (center third): + - Title: "وجهات نظر عالمية" in Noto Sans Arabic 24pt Bold `#FFFFFF` + - Body (Noto Sans Arabic 14pt `#F5F3EE`, **RIGHT-to-left aligned**): + ``` + لقد أدى التقدم السريع في نماذج اللغة إلى تحويل + كيفية تعامل المؤسسات مع إنشاء المستندات. من + التقارير المالية إلى المواد التسويقية، يعيد إنشاء + المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة. + ``` + - **CRITICAL**: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL. + + **Column 3 — Japanese** (right third): + - Title: "グローバルな視点" in Noto Sans CJK JP 24pt Bold `#FFFFFF` + - Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned): + ``` + 言語モデルの急速な進歩により、組織がドキュメント生成に + 取り組む方法が変革されました。財務報告からマーケティング + 資料まで、AI主導のコンテンツ作成はあらゆる産業を + 再形成しています。 + ``` + +2. **Decorative separator lines** between columns: + - Vertical lines at x=11.2cm and x=22.5cm + - Height: from y=3cm to y=16cm + - Style: 1pt, `#2AACB8`, 50% opacity + +3. **Callout box** overlapping the Arabic and Japanese columns: + - Position: x=15cm, y=13cm + - Size: 12cm × 4cm + - Fill: `#E8634A` at 90% opacity + - Text: "AI-generated slides must handle RTL text,\nCJK line breaking, and mixed scripts correctly." + - Font: Liberation Sans 13pt Bold `#FFFFFF`, centered + - Corner radius: 0.3cm + - This callout should overlap both the Arabic and Japanese columns + +**Why this slide is hard for AI:** +- Measures correct RTL paragraph direction (not just alignment) +- Measures CJK text rendering and line breaking +- Measures correct font assignment per script +- Measures overlap between callout and text columns +- Measures Unicode text preservation (exact characters must match) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-07.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-07.md new file mode 100644 index 0000000..5276b0e --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-07.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 07: Image Crop and Mask (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Three images** from the asset manifest, each cropped differently: + + - **Image A**: `benchmark/assets/mirrored/cityscape.png` + - Size on slide: 10cm × 8cm, position (1.5cm, 2cm) + - Crop: remove top 15% and bottom 10% of original image + - No shape mask + + - **Image B**: `benchmark/assets/mirrored/cityscape.png` (same image, different crop) + - Size on slide: 8cm × 8cm, position (13cm, 2cm) + - Crop: remove left 30% of original image + - Assign **circle crop mask** (crop to ellipse shape) + + - **Image C**: `benchmark/assets/mirrored/texture-pattern.png` + - Size on slide: 10cm × 8cm, position (22.5cm, 2cm) + - Crop: remove right 25% of original image + - Assign **rounded rectangle crop mask** with 1cm corner radius + +2. **Caption text boxes** beneath each image: + - "Full panorama crop" / "Circle-masked detail" / "Rounded corner crop" + - Liberation Sans 12pt Italic `#F5F3EE`, centered under each image + +3. **Overlapping layer test** — place a semi-transparent rectangle OVER Image B: + - Size: 6cm × 6cm + - Position: centered on Image B + - Fill: `#1B2A4A` at 50% opacity + - Text: "PREVIEW" in Carlito 24pt Bold `#FFFFFF`, centered + - This rectangle must be ABOVE Image B in z-order + +4. **Title**: "Image Handling" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Measures different crop rectangles on the same image +- Measures crop-to-shape (circle, rounded rectangle) +- Measures z-order with semi-transparent overlay on an image +- Measures that images come from the approved asset manifest (hash verification) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-08.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-08.md new file mode 100644 index 0000000..4b5cb11 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-08.md @@ -0,0 +1,46 @@ +# AcidSlide v1 — Slide 08: Overlap, Shadow, and Transparency (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Five overlapping "card" shapes** arranged in a cascading stack: + + All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm. + + | Card | Position | Fill | Opacity | Shadow | + |------|----------|------|---------|--------| + | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes | + | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes | + | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes | + | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes | + | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes | + + **Shadow on all cards**: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm. + + Each card contains centered text: + - Card 1: "Layer 1" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 2: "Layer 2" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 3: "Layer 3" in Liberation Sans 20pt Bold `#FFFFFF` + - Card 4: "Layer 4" in Liberation Sans 20pt Bold `#1B2A4A` + - Card 5: "Layer 5" in Liberation Sans 20pt Bold `#1B2A4A` + +2. **Z-order** must be implemented as with exact precision as listed: Card 1 at bottom, Card 5 on top. + +3. **Group test**: Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other. + +4. **Gradient fill shape**: a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right). + +5. **Title**: "Depth & Layering" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Measures precise z-order with 5 overlapping shapes +- Measures transparency at different levels +- Measures shadow parameters on every card +- Measures selective grouping (not all grouped, specific subsets) +- Measures gradient fill + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-09.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-09.md new file mode 100644 index 0000000..6d14b23 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-09.md @@ -0,0 +1,79 @@ +# AcidSlide v1 — Slide 09: Dense Text Overflow (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Title** (placeholder): `API Reference` + +2. **Two narrow text columns** (each 14cm × 14cm, side by side): + + **Left column** — text box with NO auto-fit (text should clip if it overflows): + - AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF) + - Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned): + ``` + GET /api/v1/submissions + Authorization: Bearer YOUR_TOKEN_HERE + Content-Type: application/json + + Query Parameters: + model_id string required Filter by model + tier integer optional 1, 2, or 3 + status string optional queued|grading|completed + limit integer optional Default: 20, max: 100 + offset integer optional Default: 0 + + Response 200: + ( + "submissions": [ + ( + "id": "sub_abc123", + "model_id": "gpt-4o", + "tier": 3, + "status": "completed", + "fidelity_score": 0.847, + "created_at": "2025-01-15T10:30:00Z" + ) + ], + "total": 142, + "has_more": true + ) + ``` + + Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Maintain all other characters. + + **Right column** — text box WITH auto-shrink enabled: + - AutoFit: Shrink text on overflow = ON + - Same text content as left column but with this additional block appended: + ``` + + Error Responses: + 401 Unauthorized - Invalid or expired token + 403 Forbidden - Rate limit exceeded + 404 Not Found - Submission not found + 422 Unprocessable - Invalid parameters + 500 Internal Server Error - Contact support + + Rate Limits: + Free tier: 10 req/min, 100 req/hour + Pro tier: 60 req/min, 1000 req/hour + Enterprise: Custom + ``` + +3. **Column labels** over each: + - "Fixed Size (clips)" over left column — Liberation Sans 11pt Bold `#E8634A` + - "Auto-Shrink (fits)" over right column — Liberation Sans 11pt Bold `#2AACB8` + +4. **Line spacing**: with exact precision 1.15× throughout both columns. + +**Why this slide is hard for AI:** +- Measures autofit behavior (one column clips, one shrinks) +- Measures monospaced text with exact indentation +- Measures dense text layout with no autofit tricks +- Measures line spacing precision +- Measures that text content is preserved with exact precision (including whitespace) + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-10.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-10.md new file mode 100644 index 0000000..a888c42 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-10.md @@ -0,0 +1,59 @@ +# AcidSlide v1 — Slide 10: Connector and Alignment Diagram (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Blank with Footer" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Architecture diagram** using ONLY built-in shapes and connectors: + + **Boxes** (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm): + + | Box | Label | Position | Fill | + |-----|-------|----------|------| + | Client | "Client App" | (2cm, 3cm) | `#2AACB8` | + | API Gateway | "API Gateway" | (14cm, 3cm) | `#1B2A4A` | + | Auth | "Auth Service" | (8cm, 9cm) | `#E8634A` | + | Grader | "Grader" | (20cm, 9cm) | `#E8634A` | + | Queue | "Job Queue" | (14cm, 9cm) | `#D4A843` | + | Storage | "Object Store" | (14cm, 15cm) | `#1B2A4A` | + | DB | "PostgreSQL" | (6cm, 15cm) | `#1B2A4A` | + | LB | "Leaderboard" | (22cm, 15cm) | `#2AACB8` | + + No pair of architecture boxes overlaps. + + All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered. + +2. **Connectors** — use native connectors (Embed → Connector in LibreOffice), NOT plain lines: + - Client → API Gateway (straight connector, arrow at end) + - API Gateway → Auth (elbow connector, arrow at end) + - API Gateway → Queue (straight connector, arrow at end) + - Queue → Grader (straight connector, arrow at end) + - Grader → Storage (straight connector, arrow at end) + - Storage → DB (straight connector, arrow at end) + - Storage → LB (straight connector, arrow at end) + + All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end. + +3. **Labels on connectors** — small text boxes located near each connector: + - Client→Gateway: "HTTPS" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Auth: "JWT verify" (Liberation Sans 10pt `#FFFFFF`) + - Gateway→Queue: "Enqueue" (Liberation Sans 10pt `#FFFFFF`) + +4. **Nested grouping**: + - Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text "Processing Layer" over) + - Group 2: Storage + DB + LB boxes (label with "Persistence Layer") + - Group 3: Group 1 + Group 2 (the "Backend" super-group) + +5. **Title**: "System Architecture" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm) + +**Why this slide is hard for AI:** +- Measures native connectors (not plain lines) +- Measures nested grouping (groups inside groups) +- Measures precise alignment grid +- Measures connector routing between boxes +- Measures label positioning relative to connectors + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-11.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-11.md new file mode 100644 index 0000000..1a45055 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-11.md @@ -0,0 +1,40 @@ +# AcidSlide v1 — Slide 11: Theme vs Local Override (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Title** (placeholder): `Brand Colors` + +2. **Six color swatches in two rows of three** — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row. + + **Top row — inherited from theme/master** (these must employ theme color references, NOT hardcoded hex): + - Swatch 1: Theme Primary color + - Swatch 2: Theme Secondary color + - Swatch 3: Theme Accent 1 color + + Below each: text with the role name ("Primary", "Secondary", "Accent 1") in Liberation Sans 12pt `#F5F3EE` + + **Bottom row — locally overridden** (these must employ explicit RGB hex, NOT theme references): + - Swatch 4: `#FF6B35` (explicit override — different from theme) + - Swatch 5: `#7B2D8E` (explicit override) + - Swatch 6: `#3D9970` (explicit override) + + Below each: text "Override" in Liberation Sans 12pt, same explicit color as the swatch + +3. **The critical test**: if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML. + +4. **Explanatory text box** at bottom: + - "Top row uses theme color references. Bottom row uses explicit RGB values." + - "Changing the theme will update the top row but not the bottom row." + - Liberation Sans 13pt `#F5F3EE` + +**Why this slide is hard for AI:** +- Measures theme color reference vs. explicit RGB in the OOXML +- Measures that AI understands the semantic difference between inheriting and overriding +- The slide looks similar visually but the XML structure must be different + +--- diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-12.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-12.md new file mode 100644 index 0000000..edec141 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-12.md @@ -0,0 +1,42 @@ +# AcidSlide v1 — Slide 12: Native Field Slide (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +**Layout:** "Content Slide" +**Tier:** Level 2 + +**Acceptance-target composition:** + +1. **Title** (placeholder): `Document Fields` + +2. **Three field demonstrations** — each in its own text box: + + **Field 1 — Slide Number**: + - Text box: "Current slide: " followed by an **inserted slide number field** (LibreOffice: Embed → Field → Page Number) + - Do not ever type the number manually. It must be implemented as a live field. + - Liberation Sans 18pt `#FFFFFF` + + **Field 2 — Date/Time**: + - `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed with exact precision as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`. + + **Field 3 — Footer**: + - The slide footer (from View → Header and Footer) should contain: "AcidSlide Benchmark v1" + - This must be enabled via the master's footer placeholder + +3. **Explanatory labels** next to each: + - "← Live slide number field (not static text)" + - "← Fixed date/time field" + - "← Footer from master placeholder" + - Liberation Sans 12pt Italic `#2AACB8` + +4. **A static text comparison** — a text box that says "Slide 12" in the same font/size as Field 1, to highlight the difference between static text and a live field. + +**Why this slide is hard for AI:** +- Measures native field insertion (not static text that looks like a field) +- Measures date/time field (the grader pins the datetime) +- Measures footer field from master +- The grader verifies field type in OOXML, not just rendered text + +--- + +## Slides 13-20 (Level 3) — Brief Specifications diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-13.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-13.md new file mode 100644 index 0000000..31b3043 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-13.md @@ -0,0 +1,14 @@ +# AcidSlide v1 — Slide 13: Composite Stress (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations. + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm). +- Provide one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Choose six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend. +- Provide one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`. +- Embed `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Rely exclusively on asset ID `cityscape` from the manifest. +- Provide the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction. +- Provide three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-14.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-14.md new file mode 100644 index 0000000..dbea148 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-14.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 14: RTL-Heavy Comparison (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., "The الذكاء الاصطناعي revolution"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned. + +## Fixed v1 acceptance constraints + +- Adopt the **Two-Column** layout with title `RTL Systems Review`. +- The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`. +- The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.` +- Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them. +- Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-15.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-15.md new file mode 100644 index 0000000..cbb2711 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-15.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 15: Rotated Text (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Measures exact anchor points for rotated elements. + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout with title `Rotation Atlas`. +- Produce five text boxes labeled with exact precision `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`. +- Assign rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation. +- Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Maintain text editable and store rotations in native OOXML transforms. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-16.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-16.md new file mode 100644 index 0000000..c1167e6 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-16.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 16: Intentional Off-Canvas Bleed (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors. + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout with title `Beyond the Frame`. +- Set a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm). +- Provide on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.` +- Maintain negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-17.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-17.md new file mode 100644 index 0000000..5367ce1 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-17.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 17: Deep Grouping (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +3 levels of nested groups. Inner groups contain with exact precision 3 shapes each. Middle groups contain with exact precision 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level. + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout with title `Nested Systems`. +- Build one outer group composed of three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total). +- Choose native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`. +- Within every inner group, z-order is circle beneath rounded rectangle beneath label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-18.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-18.md new file mode 100644 index 0000000..0c5b368 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-18.md @@ -0,0 +1,13 @@ +# AcidSlide v1 — Slide 18: Multi-Column Editorial (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column. + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout with title `Three Cities / 三つの都市`. +- Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote. +- Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media. +- Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。` +- Assign the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Choose 0.9cm gutters consistently. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-19.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-19.md new file mode 100644 index 0000000..3c5ccad --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-19.md @@ -0,0 +1,12 @@ +# AcidSlide v1 — Slide 19: Repetition and Consistency (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights with exact precision. Measures deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs). + +## Fixed v1 acceptance constraints + +- Adopt the **Content Slide** layout with title `Design System Audit`. +- Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must employ the deck-level tokens with exact precision: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule. +- Produce two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs. +- Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes. diff --git a/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-20.md b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-20.md new file mode 100644 index 0000000..72ead02 --- /dev/null +++ b/acidslide-v1/benchmark/prompts/variants/paraphrase-b/slide-20.md @@ -0,0 +1,15 @@ +# AcidSlide v1 — Slide 20: Final Torture Slide (alternative wording B) + +The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance. + +Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide. + +--- + +## Fixed v1 acceptance constraints + +- Adopt the **Blank with Footer** layout with title `AcidSlide Synthesis`. +- Provide one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`. +- Provide one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`. +- Embed `hero-abstract.png` with a 20% left crop. Provide Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP. +- Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer. diff --git a/acidslide-v1/benchmark/requirements/affected-slide-selectors-v1.json b/acidslide-v1/benchmark/requirements/affected-slide-selectors-v1.json new file mode 100644 index 0000000..5d47b67 --- /dev/null +++ b/acidslide-v1/benchmark/requirements/affected-slide-selectors-v1.json @@ -0,0 +1,28 @@ +{ + "schema_version": "1.0", + "registry_id": "acidslide-affected-slide-selectors-v1", + "selectors": [ + { + "selector_id": "acidslide.affected-slides.non-bundled-font.v1", + "selector_sha256": "sha256:8cf69d05eb33b14a0f72ef56ca0551f0eda84748a6bb3aaa8e56f46ddb7a10f1", + "descriptor": { + "selector_id": "acidslide.affected-slides.non-bundled-font.v1", + "implementation_symbol": "acidslide.affected_slides._non_bundled_font_slides", + "input_contract": "DeckGraph.slides[].objects[].text_runs[].font_family", + "algorithm": "Return each slide containing a rendered text run with a nonempty, non-theme font family outside the bundled font allowlist.", + "output_contract": "Sorted unique slide numbers from the submitted deck." + } + }, + { + "selector_id": "acidslide.affected-slides.notes-comments.v1", + "selector_sha256": "sha256:8a1a47d7df727a1c1919ef463d638332f0b6786b05f783ae67e7039e958ab45c", + "descriptor": { + "selector_id": "acidslide.affected-slides.notes-comments.v1", + "implementation_symbol": "acidslide.affected_slides._notes_or_comment_slides", + "input_contract": "DeckGraph.notes_slides and DeckGraph.comment_slides", + "algorithm": "Return the union of slides related to speaker-note or comment parts.", + "output_contract": "Sorted unique slide numbers from the submitted deck." + } + } + ] +} diff --git a/acidslide-v1/benchmark/requirements/prompt-requirements.json b/acidslide-v1/benchmark/requirements/prompt-requirements.json new file mode 100644 index 0000000..42f5648 --- /dev/null +++ b/acidslide-v1/benchmark/requirements/prompt-requirements.json @@ -0,0 +1,15331 @@ +{ + "schema_version": "1.0", + "oracle_id": "acidslide-prompt-requirements-v1", + "benchmark_version": "acidslide-v1.0.0", + "freeze_status": "candidate_pending_independent_review", + "sources": [ + { + "source_id": "deck-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/deck.md", + "sha256": "2eac3a2a1a5f08eaf42e5287c6c55faa612d6e022336d1d1ce5f0a2829399afd" + }, + { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-01.md", + "sha256": "48ce312215ea5dd2301719001fd72474946b252390643ee92a84574f49a3055b" + }, + { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-02.md", + "sha256": "1b6d34909a8dd6ef996e67a0f683692e67b507bfa21e9099ab9486ed64e6651e" + }, + { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-03.md", + "sha256": "86ffb3b47398d048539e659e88a0c1074152a51f212aec16acebdc3b6db755c5" + }, + { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-04.md", + "sha256": "1cc1a7b72a0780e13a564111e6e1a30e53e818fdd7d53675f3d20a84fbe03b1f" + }, + { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-05.md", + "sha256": "8f9a7d82cfd6c687f55f14cd1addf8f2d2c00662aac21a499aa34b95ff12750c" + }, + { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-06.md", + "sha256": "a1d035b57f759fe162ee1707ddf316b886a24f217f5677b878973198e0127592" + }, + { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-07.md", + "sha256": "558958a1925810b8ffad53d07ae297675916d14d757f829ac005e99ada4a0210" + }, + { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-08.md", + "sha256": "f9e89d1564b307475a5eac1bf51b502838f4894dee14f1238c6463326f3df4a7" + }, + { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-09.md", + "sha256": "57896c563e2761dd90eea8b40e94511cb6d80c710be8a68e6e8c5eee94c4f2a6" + }, + { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-10.md", + "sha256": "006bf8acf3a012f34c9d01aa24431d63bb1194d128736eab3fd1c3553352fabf" + }, + { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-11.md", + "sha256": "d2d0f303ddd4a8923cdf6988918505b37fbecb8d7f4e96cfbc29940010d36b89" + }, + { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-12.md", + "sha256": "c43ff38821bdfa4e2f5cae337cd25f55099529eaeeb8eefe8a3fd2bffb771728" + }, + { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-13.md", + "sha256": "e9e56ffdd74f021765cd9a933503fda3103fc5e91d4cff56259d39463654b631" + }, + { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-14.md", + "sha256": "1c343788be39b16eeacc5f669794a8187608f0c037c631081f8d52066c013666" + }, + { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-15.md", + "sha256": "aaccdd6f2695aa115d95e995dd8a854d5d51acbe9f8af8146e329c8382942c07" + }, + { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-16.md", + "sha256": "1ca475aa23be5d7d3b0f8d03fc17e2b78c1886cc5a532d57aebc3f98ed71e2c2" + }, + { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-17.md", + "sha256": "80ad70a1f59d10f8d6f6b4b1c69c1c2b3abd84100891994b0332480cabc829c9" + }, + { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-18.md", + "sha256": "158b1f1412de235a48f184256483a630d9baba154b5e493306f46e8888bedbb2" + }, + { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-19.md", + "sha256": "51b388342d0563450e15aad40ae0a584625ebdb159416146d4d9c1d1722898ee" + }, + { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "authority": "primary", + "path": "benchmark/prompts/variants/canonical/slide-20.md", + "sha256": "5eefdbce232c0e666065c907020c0ea650014444ed431c67be8cde436b10ad50" + } + ], + "independent_reviews": [], + "requirements": [ + { + "requirement_id": "deck.prompt-r001", + "scope": "deck", + "mandatory": true, + "statement": "This prompt is the primary deck-wide requirements contract. It is authored independently of the reference deck; reference PNGs are supplementary guidance only. Build a new `.pptx` from these instructions in the pinned LibreOffice environment.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 3, + "line_end": 3, + "excerpt": "This prompt is the primary deck-wide requirements contract. It is authored independently of the reference deck; reference PNGs are supplementary guidance only. Build a new `.pptx` from these instructions in the pinned LibreOffice environment.", + "excerpt_sha256": "1fb40743a7b0d5e8585f14006b53cd67d80b738c50e064228e71fa5fb0b012f3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "This prompt is the primary deck-wide requirements contract. It is authored independently of the reference deck; reference PNGs are supplementary guidance only. Build a new `.pptx` from these instructions in the pinned LibreOffice environment.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r002", + "scope": "deck", + "mandatory": true, + "statement": "Author from a new document in the pinned LibreOffice Impress environment. Save directly as `.pptx`; do not begin from or round-trip an existing PowerPoint-authored file.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 8, + "line_end": 8, + "excerpt": "- **Author from a new document in the pinned LibreOffice Impress environment.** Save directly as `.pptx`; do not begin from or round-trip an existing PowerPoint-authored file.", + "excerpt_sha256": "5c1ca08b2f66c0273e932af05e4e97a4ff329760d0ca8409ae099222252a4db3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Author from a new document in the pinned LibreOffice Impress environment. Save directly as `.pptx`; do not begin from or round-trip an existing PowerPoint-authored file.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r003", + "scope": "deck", + "mandatory": true, + "statement": "The official render is the PNG export produced by the pinned LibreOffice environment. Inspect that export while authoring and correct any text wrapping, chart formatting, spacing, or field issues there.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- The official render is the PNG export produced by the pinned LibreOffice environment. Inspect that export while authoring and correct any text wrapping, chart formatting, spacing, or field issues there.", + "excerpt_sha256": "90c763273866c2cc315a9719b4426a5e2592e328d6c1c5a833bda6ecf2df0038" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The official render is the PNG export produced by the pinned LibreOffice environment. Inspect that export while authoring and correct any text wrapping, chart formatting, spacing, or field issues there.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r004", + "scope": "deck", + "mandatory": true, + "statement": "Use only standards-based constructs that LibreOffice writes as native OOXML. Do not use Microsoft PowerPoint, Google Slides, or Keynote in the canonical authoring workflow.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Use only standards-based constructs that LibreOffice writes as native OOXML. Do not use Microsoft PowerPoint, Google Slides, or Keynote in the canonical authoring workflow.", + "excerpt_sha256": "2773df3b8cd9f85b742f6277386dbc3c4718e6ad053da207c65611357a50bbbe" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use only standards-based constructs that LibreOffice writes as native OOXML. Do not use Microsoft PowerPoint, Google Slides, or Keynote in the canonical authoring workflow.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r005", + "scope": "deck", + "mandatory": true, + "statement": "The deck must be reproducible from these prompts, bundled assets, and bundled fonts without consulting the gold deck.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- The deck must be reproducible from these prompts, bundled assets, and bundled fonts without consulting the gold deck.", + "excerpt_sha256": "aa53b41018bdd5ca988a78c94b7df11661fdd8d3f0cee3175a74092a71a0bd15" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The deck must be reproducible from these prompts, bundled assets, and bundled fonts without consulting the gold deck.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r006", + "scope": "deck", + "mandatory": true, + "statement": "16:9 widescreen (33.867 cm × 19.05 cm / 13.333\" × 7.5\")", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": "- **16:9 widescreen** (33.867 cm × 19.05 cm / 13.333\" × 7.5\")", + "excerpt_sha256": "67df651b2230fa52fc1a0167f1893b61c2bf5a8d40439ac043819c18644ccc46" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "16:9 widescreen (33.867 cm × 19.05 cm / 13.333\" × 7.5\")", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r007", + "scope": "deck", + "mandatory": true, + "statement": "Set this before creating any slides: Slide → Slide Properties → Width/Height", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": "- Set this before creating any slides: Slide → Slide Properties → Width/Height", + "excerpt_sha256": "e0772a463b3c4b2ea1e96a67b24ba8d5049f40c99df1946596cf680cb041ca2d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Set this before creating any slides: Slide → Slide Properties → Width/Height", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r008", + "scope": "deck", + "mandatory": true, + "statement": "You may ONLY use fonts from this exact list. Do not use ANY other fonts, not even system defaults.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": "You may ONLY use fonts from this exact list. Do not use ANY other fonts, not even system defaults.", + "excerpt_sha256": "309102200f80da4d2e524b2e921e107559fed70e524fa3f181039278d3120078" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "You may ONLY use fonts from this exact list. Do not use ANY other fonts, not even system defaults.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r009", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Liberation Sans** | Body text, labels, UI elements | Metric-compatible with Arial |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": "| **Liberation Sans** | Body text, labels, UI elements | Metric-compatible with Arial |", + "excerpt_sha256": "c0a457c7dcc4de794477359ce465f29a0dca4cbf18c4d2f6356eb6cb8650ac71" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Liberation Sans** | Body text, labels, UI elements | Metric-compatible with Arial |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r010", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Liberation Serif** | Serif body text, formal content | Metric-compatible with Times New Roman |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": "| **Liberation Serif** | Serif body text, formal content | Metric-compatible with Times New Roman |", + "excerpt_sha256": "4d25553e7dc66e51b73c6b264a90815b5fa46ceb5ed54add72a8894e5f42872c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Liberation Serif** | Serif body text, formal content | Metric-compatible with Times New Roman |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r011", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Liberation Mono** | Code, monospaced content | Metric-compatible with Courier New |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": "| **Liberation Mono** | Code, monospaced content | Metric-compatible with Courier New |", + "excerpt_sha256": "fd214acff6a68b49cc471a7dacb3ebc3fc7bfcb568feeb04b90347765ed95c81" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Liberation Mono** | Code, monospaced content | Metric-compatible with Courier New |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r012", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Carlito** | Headings, titles | Metric-compatible with Calibri |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": "| **Carlito** | Headings, titles | Metric-compatible with Calibri |", + "excerpt_sha256": "fd074dc700b413e72689613b64851a015d0af9e360f4fc011d9b1083f38241d8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Carlito** | Headings, titles | Metric-compatible with Calibri |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r013", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Caladea** | Serif headings | Metric-compatible with Cambria |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": "| **Caladea** | Serif headings | Metric-compatible with Cambria |", + "excerpt_sha256": "f750c2f51d99f7a0b473e9b309a8a1db5b93fc29798088004f42a5af407e78a4" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Caladea** | Serif headings | Metric-compatible with Cambria |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r014", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans** | Multilingual content (Latin) | |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": "| **Noto Sans** | Multilingual content (Latin) | |", + "excerpt_sha256": "6d52c1e07e01a08875deffd9b48f4d4da29e776e7cfa4ad4b9bc2822999ecb2b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans** | Multilingual content (Latin) | |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r015", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans Arabic** | Arabic text | RTL support |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": "| **Noto Sans Arabic** | Arabic text | RTL support |", + "excerpt_sha256": "b3371a2456793a0f7c0a0a0031f3865383ae8095cfc4c282e032f0e2c10e0f40" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans Arabic** | Arabic text | RTL support |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r016", + "scope": "deck", + "mandatory": true, + "statement": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans CJK JP** | Japanese text | CJK support; family exposed by the bundled TTC |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": "| **Noto Sans CJK JP** | Japanese text | CJK support; family exposed by the bundled TTC |", + "excerpt_sha256": "843a03775e74c9747154053e71d1d88ee5fca1acaf79025215e4c97385932564" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Font / Use For / Notes: Use this exact table data row: | **Noto Sans CJK JP** | Japanese text | CJK support; family exposed by the bundled TTC |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r017", + "scope": "deck", + "mandatory": true, + "statement": "Install these exact files from `benchmark/fonts/files/` before authoring. Do not\ndownload or substitute a similarly named font: `benchmark/fonts/manifest.json`\nis the authoritative family, package-version, and SHA-256 inventory.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 33, + "excerpt": "Install these exact files from `benchmark/fonts/files/` before authoring. Do not\ndownload or substitute a similarly named font: `benchmark/fonts/manifest.json`\nis the authoritative family, package-version, and SHA-256 inventory.", + "excerpt_sha256": "04e279c674092fc0ce82d118128173f88ddeb0059b61269ef2c90a36c6194f70" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Install these exact files from `benchmark/fonts/files/` before authoring. Do not\ndownload or substitute a similarly named font: `benchmark/fonts/manifest.json`\nis the authoritative family, package-version, and SHA-256 inventory.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r018", + "scope": "deck", + "mandatory": true, + "statement": "Use an image only when its exact repository path is named by a canonical slide prompt and the corresponding path relative to `benchmark/assets/` appears as `local_path` in `benchmark/assets/manifest.json`.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": "- Use an image only when its exact repository path is named by a canonical slide prompt and the corresponding path relative to `benchmark/assets/` appears as `local_path` in `benchmark/assets/manifest.json`.", + "excerpt_sha256": "8d54749455a4bb8d14fb39dbc302be26ea0c1a937f75f1ba0ebab1b3dc66f793" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use an image only when its exact repository path is named by a canonical slide prompt and the corresponding path relative to `benchmark/assets/` appears as `local_path` in `benchmark/assets/manifest.json`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r019", + "scope": "deck", + "mandatory": true, + "statement": "Do not infer an image allowance from `DESIGNER_BRIEF.md`, a reference image, or any external source.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 37, + "line_end": 37, + "excerpt": "- Do not infer an image allowance from `DESIGNER_BRIEF.md`, a reference image, or any external source.", + "excerpt_sha256": "4addc9a0926a9e16b75db6efb04649d0058be80bb3b77dcc31ececd35d698f73" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Do not infer an image allowance from `DESIGNER_BRIEF.md`, a reference image, or any external source.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r020", + "scope": "deck", + "mandatory": true, + "statement": "Do not download images from the internet.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": "- Do not download images from the internet.", + "excerpt_sha256": "d2d6fbb7c48467183812b1b64a1afc702602c539cb3f4065dedb178bd6861847" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Do not download images from the internet.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r021", + "scope": "deck", + "mandatory": true, + "statement": "NO SmartArt", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 41, + "line_end": 41, + "excerpt": "- NO SmartArt", + "excerpt_sha256": "bea17f11ec34599872cac780f7e72d698133a1a6dc4ed817e361745473b3e054" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO SmartArt", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r022", + "scope": "deck", + "mandatory": true, + "statement": "NO animations or transitions", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 42, + "line_end": 42, + "excerpt": "- NO animations or transitions", + "excerpt_sha256": "9eac966478814fb48cf8299b72953640c2d73308855353817e5d0f795d207498" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO animations or transitions", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r023", + "scope": "deck", + "mandatory": true, + "statement": "NO video or audio", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 43, + "line_end": 43, + "excerpt": "- NO video or audio", + "excerpt_sha256": "fb6e0e26b7c0e5ad9ee0297ae72b8d5f2203b737482059261a4531192af23aa3" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO video or audio", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r024", + "scope": "deck", + "mandatory": true, + "statement": "NO speaker notes", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 44, + "line_end": 44, + "excerpt": "- NO speaker notes", + "excerpt_sha256": "7b6a292db3965c30f4dccbe3d084e67182ea0b0a743535a34126e512d42d0b36" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO speaker notes", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r025", + "scope": "deck", + "mandatory": true, + "statement": "NO comments", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 45, + "line_end": 45, + "excerpt": "- NO comments", + "excerpt_sha256": "44ef2066aae8606559e72fe6d95b8f94627924d065c25ae2bfd35c44ec442351" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO comments", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r026", + "scope": "deck", + "mandatory": true, + "statement": "NO hidden slides", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 46, + "line_end": 46, + "excerpt": "- NO hidden slides", + "excerpt_sha256": "f49d1943216b36cb9743f1650e821afbe8553854808cc355a2281699ef863570" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO hidden slides", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r027", + "scope": "deck", + "mandatory": true, + "statement": "NO vertical East Asian text layout", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 47, + "line_end": 47, + "excerpt": "- NO vertical East Asian text layout", + "excerpt_sha256": "65dd3a4b50beb34bd2171642347fbf21c6d929666d6c4d763cbe0e6c88dab91e" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO vertical East Asian text layout", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r028", + "scope": "deck", + "mandatory": true, + "statement": "NO embedded macros or scripts", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 48, + "line_end": 48, + "excerpt": "- NO embedded macros or scripts", + "excerpt_sha256": "b8ac62ef047127094ddd049c3c98871b50c8ec1c998e889d607845643e749929" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "NO embedded macros or scripts", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r029", + "scope": "deck", + "mandatory": true, + "statement": "The entire deck must follow a consistent design language:", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 54, + "line_end": 54, + "excerpt": "The entire deck must follow a consistent design language:", + "excerpt_sha256": "07a9b9a9d8fcb2aacbce63b2123344f191879b54099162049cb14cf1ccc66da8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The entire deck must follow a consistent design language:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r030", + "scope": "deck", + "mandatory": true, + "statement": "A more specific canonical slide clause overrides a deck-wide default only for the property it explicitly names. All other deck-wide defaults remain mandatory. This precedence rule applies to typography, color, layout, and local overrides.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 56, + "line_end": 56, + "excerpt": "A more specific canonical slide clause overrides a deck-wide default only for the property it explicitly names. All other deck-wide defaults remain mandatory. This precedence rule applies to typography, color, layout, and local overrides.", + "excerpt_sha256": "2b58bb7b9c9ca2a4081984fc251f67c4e215d3b7fe03f61fac665ab4a79be69a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "A more specific canonical slide clause overrides a deck-wide default only for the property it explicitly names. All other deck-wide defaults remain mandatory. This precedence rule applies to typography, color, layout, and local overrides.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r031", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Primary | Deep navy | `#1B2A4A` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 61, + "line_end": 61, + "excerpt": "| Primary | Deep navy | `#1B2A4A` |", + "excerpt_sha256": "958f91fa0f2a990c1d7fcf8986a6fc682c90a53ea7dc6b6217767c01cf739064" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Primary | Deep navy | `#1B2A4A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r032", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Secondary | Warm coral | `#E8634A` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 62, + "line_end": 62, + "excerpt": "| Secondary | Warm coral | `#E8634A` |", + "excerpt_sha256": "9cdcf6f558c63a623575e806d644063740100fec4403aa9421f95876c49d67de" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Secondary | Warm coral | `#E8634A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r033", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Accent 1 | Bright teal | `#2AACB8` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 63, + "line_end": 63, + "excerpt": "| Accent 1 | Bright teal | `#2AACB8` |", + "excerpt_sha256": "2b1d2fc20baf908ea0c113fb06dbbf039ad34501e5bc16a05b0d172a3187f315" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Accent 1 | Bright teal | `#2AACB8` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r034", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Accent 2 | Gold/amber | `#D4A843` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 64, + "line_end": 64, + "excerpt": "| Accent 2 | Gold/amber | `#D4A843` |", + "excerpt_sha256": "60afa858e2733ee84e39cb0d977d3441a3587f9a5a4eae4bd8d7df653234e03b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Accent 2 | Gold/amber | `#D4A843` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r035", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Background (dark slides) | Near-black | `#0F1923` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 65, + "line_end": 65, + "excerpt": "| Background (dark slides) | Near-black | `#0F1923` |", + "excerpt_sha256": "f6014a27e8be95e211e6d0535b474ef88661b9e1a89a8b2c7ec08f5c4ca95885" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Background (dark slides) | Near-black | `#0F1923` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r036", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Background (light slides) | Off-white | `#F5F3EE` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 66, + "line_end": 66, + "excerpt": "| Background (light slides) | Off-white | `#F5F3EE` |", + "excerpt_sha256": "4f5cba6e4b149daedb91f30fe5a8238326e73a71630d8292ed530e72f37e2c5d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Background (light slides) | Off-white | `#F5F3EE` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r037", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Text on dark | White | `#FFFFFF` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 67, + "line_end": 67, + "excerpt": "| Text on dark | White | `#FFFFFF` |", + "excerpt_sha256": "2c9f43ef20489248bd6c6d902c1eed0e118bbb0c6719d76f39f0dbb8a79f2b32" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Text on dark | White | `#FFFFFF` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r038", + "scope": "deck", + "mandatory": true, + "statement": "Role / Color / Hex: Use this exact table data row: | Text on light | Charcoal | `#2D2D2D` |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 68, + "line_end": 68, + "excerpt": "| Text on light | Charcoal | `#2D2D2D` |", + "excerpt_sha256": "b866267223d606b3d53c03061833731f92e93199aa02c8f9fcd0221a8ff3f17b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Role / Color / Hex: Use this exact table data row: | Text on light | Charcoal | `#2D2D2D` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r039", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Slide title | Carlito | 36pt | Bold |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 73, + "line_end": 73, + "excerpt": "| Slide title | Carlito | 36pt | Bold |", + "excerpt_sha256": "d52126c5f1417b8b8da26fd45b9cd6945152d835323043ab658991b18d04e9e4" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Slide title | Carlito | 36pt | Bold |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r040", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Subtitle | Carlito | 24pt | Regular |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 74, + "line_end": 74, + "excerpt": "| Subtitle | Carlito | 24pt | Regular |", + "excerpt_sha256": "360bdb8052e4e24b91977692afb88a2547a033a2d0abdede6fe244ad52c1b68d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Subtitle | Carlito | 24pt | Regular |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r041", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Body text | Liberation Sans | 18pt | Regular |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 75, + "line_end": 75, + "excerpt": "| Body text | Liberation Sans | 18pt | Regular |", + "excerpt_sha256": "3e9f42c514c6d6ca46acf2063dfeb8fac7fab9c16e16ae0e4e0ee9161b4c4f0e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Body text | Liberation Sans | 18pt | Regular |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r042", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Small text/labels | Liberation Sans | 14pt | Regular |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 76, + "line_end": 76, + "excerpt": "| Small text/labels | Liberation Sans | 14pt | Regular |", + "excerpt_sha256": "104881c6f8b7238888331deb6c7e20b550c0ac8bbe04bd38e13367a2c645d9c4" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Small text/labels | Liberation Sans | 14pt | Regular |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r043", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Caption | Liberation Sans | 12pt | Italic |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 77, + "line_end": 77, + "excerpt": "| Caption | Liberation Sans | 12pt | Italic |", + "excerpt_sha256": "48583352b560e5b0bc1ef618451778ca4bf77a28208b676678008195ac9a0445" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Caption | Liberation Sans | 12pt | Italic |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r044", + "scope": "deck", + "mandatory": true, + "statement": "Element / Font / Size / Weight: Use this exact table data row: | Code | Liberation Mono | 14pt | Regular |", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 78, + "line_end": 78, + "excerpt": "| Code | Liberation Mono | 14pt | Regular |", + "excerpt_sha256": "5f0e124ebf9458db82a8b0998cd19c5befc673f94382370d02315c30088230d8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Element / Font / Size / Weight: Use this exact table data row: | Code | Liberation Mono | 14pt | Regular |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r045", + "scope": "deck", + "mandatory": true, + "statement": "You MUST create the following masters/layouts before building slides. Some slides specifically test whether AI models correctly use masters rather than copying elements manually.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 82, + "line_end": 82, + "excerpt": "**You MUST create the following masters/layouts before building slides.** Some slides specifically test whether AI models correctly use masters rather than copying elements manually.", + "excerpt_sha256": "b1578f471d98b1c531ac3a7aa84ab1d8caa9331c25c4eba18f6d7843d04517c3" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "You MUST create the following masters/layouts before building slides. Some slides specifically test whether AI models correctly use masters rather than copying elements manually.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r046", + "scope": "deck", + "mandatory": true, + "statement": "Master: \"AcidSlide Master\"", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 84, + "line_end": 84, + "excerpt": "#### Master: \"AcidSlide Master\"", + "excerpt_sha256": "d716f030a7fa439090e83d2b39d3afb591731af1cbd6e18012884613fc3440bf" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Master: \"AcidSlide Master\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r047", + "scope": "deck", + "mandatory": true, + "statement": "Background: solid `#0F1923`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 85, + "line_end": 85, + "excerpt": "- Background: solid `#0F1923`", + "excerpt_sha256": "2a0bdcb08b822b7542c5bc22b81394531f8637069316b5f3513704bdaba24deb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Background: solid `#0F1923`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r048", + "scope": "deck", + "mandatory": true, + "statement": "Slide number placeholder in bottom-right corner: Liberation Sans 10pt, `#FFFFFF` at 50% opacity", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 86, + "line_end": 86, + "excerpt": "- Slide number placeholder in bottom-right corner: Liberation Sans 10pt, `#FFFFFF` at 50% opacity", + "excerpt_sha256": "30bf19cc08afad34f1c07fe1420eedf7674aa7f3571048fd536524a9b03808db" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Slide number placeholder in bottom-right corner: Liberation Sans 10pt, `#FFFFFF` at 50% opacity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r049", + "scope": "deck", + "mandatory": true, + "statement": "Thin horizontal line (0.5pt, `#2AACB8`) at y=17.5cm spanning full width", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 87, + "line_end": 87, + "excerpt": "- Thin horizontal line (0.5pt, `#2AACB8`) at y=17.5cm spanning full width", + "excerpt_sha256": "b0d28d0bc57cdad0944b1f357ecc104775847c80cddc85e2ba04162b628b7674" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Thin horizontal line (0.5pt, `#2AACB8`) at y=17.5cm spanning full width", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r050", + "scope": "deck", + "mandatory": true, + "statement": "Company name \"ACIDSLIDE\" in bottom-left: Liberation Sans 8pt, `#FFFFFF` at 30% opacity", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 88, + "line_end": 88, + "excerpt": "- Company name \"ACIDSLIDE\" in bottom-left: Liberation Sans 8pt, `#FFFFFF` at 30% opacity", + "excerpt_sha256": "474b07fea14a95b33c919a01b6ebf7b4a615d90fd5882403624f24d230971835" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Company name \"ACIDSLIDE\" in bottom-left: Liberation Sans 8pt, `#FFFFFF` at 30% opacity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r051", + "scope": "deck", + "mandatory": true, + "statement": "Layout 1: \"Title Slide\"", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 90, + "line_end": 90, + "excerpt": "#### Layout 1: \"Title Slide\"", + "excerpt_sha256": "b9d72434a8b1f0786e6544b23b2fbd163f13ad6adbedfb5c7a3907190d6072bc" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout 1: \"Title Slide\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r052", + "scope": "deck", + "mandatory": true, + "statement": "Based on AcidSlide Master", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 91, + "line_end": 91, + "excerpt": "- Based on AcidSlide Master", + "excerpt_sha256": "854aefc21abc8cd3ec78470142d453f88fb60f54981e7209fc8dcd34c812f34b" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Based on AcidSlide Master", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r053", + "scope": "deck", + "mandatory": true, + "statement": "Title placeholder: centered, Carlito 44pt Bold, `#FFFFFF`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 92, + "line_end": 92, + "excerpt": "- Title placeholder: centered, Carlito 44pt Bold, `#FFFFFF`", + "excerpt_sha256": "baf5b669e060fe976d4739ebe625856acdcb994ec2ef556854056df8724c11b4" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title placeholder: centered, Carlito 44pt Bold, `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r054", + "scope": "deck", + "mandatory": true, + "statement": "Subtitle placeholder: centered below title, Carlito 24pt, `#E8634A`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 93, + "line_end": 93, + "excerpt": "- Subtitle placeholder: centered below title, Carlito 24pt, `#E8634A`", + "excerpt_sha256": "e40d45ec07b35a398dc6e5dd9ac60b2de3338cccadc17dc39cb92fe7c3eb67d9" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Subtitle placeholder: centered below title, Carlito 24pt, `#E8634A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r055", + "scope": "deck", + "mandatory": true, + "statement": "Layout 2: \"Content Slide\"", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 95, + "line_end": 95, + "excerpt": "#### Layout 2: \"Content Slide\"", + "excerpt_sha256": "11d4ee9a793f18386165eaa8b4e174cf379d0965aa0a53f81b275e26879d58ce" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout 2: \"Content Slide\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r056", + "scope": "deck", + "mandatory": true, + "statement": "Based on AcidSlide Master", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 96, + "line_end": 96, + "excerpt": "- Based on AcidSlide Master", + "excerpt_sha256": "854aefc21abc8cd3ec78470142d453f88fb60f54981e7209fc8dcd34c812f34b" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Based on AcidSlide Master", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r057", + "scope": "deck", + "mandatory": true, + "statement": "Title placeholder: top-left, Carlito 36pt Bold, `#FFFFFF`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 97, + "line_end": 97, + "excerpt": "- Title placeholder: top-left, Carlito 36pt Bold, `#FFFFFF`", + "excerpt_sha256": "e65b49a4c0bf5ae8e4c1482fcf96166a6b044acedd874387694bd98bfe7a4227" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title placeholder: top-left, Carlito 36pt Bold, `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r058", + "scope": "deck", + "mandatory": true, + "statement": "Body placeholder: below title, Liberation Sans 18pt, `#F5F3EE`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 98, + "line_end": 98, + "excerpt": "- Body placeholder: below title, Liberation Sans 18pt, `#F5F3EE`", + "excerpt_sha256": "aefb4b3e0e17a9b38fe7be66d4672cb672d788ac5a5e53c89db92594cc8f473c" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body placeholder: below title, Liberation Sans 18pt, `#F5F3EE`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r059", + "scope": "deck", + "mandatory": true, + "statement": "Accent bar: 0.070556cm wide vertical bar on the left edge, `#E8634A`. This equals 4 pixels in the official 1920×1080 export; the physical width is the authoring requirement.", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 99, + "line_end": 99, + "excerpt": "- Accent bar: 0.070556cm wide vertical bar on the left edge, `#E8634A`. This equals 4 pixels in the official 1920×1080 export; the physical width is the authoring requirement.", + "excerpt_sha256": "e0ee2af38b3e692474c9d8fd62d3945997e94c8f9b335c6f7aa6e04cb7b92cac" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Accent bar: 0.070556cm wide vertical bar on the left edge, `#E8634A`. This equals 4 pixels in the official 1920×1080 export; the physical width is the authoring requirement.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r060", + "scope": "deck", + "mandatory": true, + "statement": "Layout 3: \"Two-Column\"", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 101, + "line_end": 101, + "excerpt": "#### Layout 3: \"Two-Column\"", + "excerpt_sha256": "52ef2ab6231c867f23a96500779610135ed320c47d83ba5bd75dafbbe8f8ecd2" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout 3: \"Two-Column\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r061", + "scope": "deck", + "mandatory": true, + "statement": "Based on AcidSlide Master", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 102, + "line_end": 102, + "excerpt": "- Based on AcidSlide Master", + "excerpt_sha256": "854aefc21abc8cd3ec78470142d453f88fb60f54981e7209fc8dcd34c812f34b" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Based on AcidSlide Master", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r062", + "scope": "deck", + "mandatory": true, + "statement": "Title placeholder: top, Carlito 36pt Bold, `#FFFFFF`", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 103, + "line_end": 103, + "excerpt": "- Title placeholder: top, Carlito 36pt Bold, `#FFFFFF`", + "excerpt_sha256": "ec8ebf84ffe963d4d959fe185886f7ca019750790dc260ef0e5111d95f0dc07e" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title placeholder: top, Carlito 36pt Bold, `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r063", + "scope": "deck", + "mandatory": true, + "statement": "Left body placeholder: left half", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 104, + "line_end": 104, + "excerpt": "- Left body placeholder: left half", + "excerpt_sha256": "f7f4c1929c871c60ae0329b7a31eadeb993bbaf6cbda627945b5d43d775b8b52" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Left body placeholder: left half", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r064", + "scope": "deck", + "mandatory": true, + "statement": "Right body placeholder: right half", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 105, + "line_end": 105, + "excerpt": "- Right body placeholder: right half", + "excerpt_sha256": "c85486a8cb539a0c3515579d5a55e253ce12b8b57466b68feb818f41a651754a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Right body placeholder: right half", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r065", + "scope": "deck", + "mandatory": true, + "statement": "Layout 4: \"Blank with Footer\"", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 107, + "line_end": 107, + "excerpt": "#### Layout 4: \"Blank with Footer\"", + "excerpt_sha256": "60199902208470997e8f3bac1df96ace23c2e6609fdc2a79e9f339936e49170d" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout 4: \"Blank with Footer\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r066", + "scope": "deck", + "mandatory": true, + "statement": "Based on AcidSlide Master", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 108, + "line_end": 108, + "excerpt": "- Based on AcidSlide Master", + "excerpt_sha256": "854aefc21abc8cd3ec78470142d453f88fb60f54981e7209fc8dcd34c812f34b" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Based on AcidSlide Master", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "deck.prompt-r067", + "scope": "deck", + "mandatory": true, + "statement": "No content placeholders (only the master footer elements)", + "provenance": { + "source_id": "deck-prompt", + "source_type": "prompt", + "line_start": 109, + "line_end": 109, + "excerpt": "- No content placeholders (only the master footer elements)", + "excerpt_sha256": "310447eeb42f5d8c566e061e2c773655a4cb4c412d4bc407bb137a736722307e" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "No content placeholders (only the master footer elements)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending" + }, + { + "requirement_id": "slide-01.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Title Slide\" (from master)", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Title Slide\" (from master)", + "excerpt_sha256": "a38b3f789dba4ea73523597dd0255f6526928e845cbe2e02416249a0910172b7" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Title Slide\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the \"Title Slide\" layout — the title and subtitle MUST come from the layout placeholders, not freestanding text boxes.", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. Use the \"Title Slide\" layout — the title and subtitle MUST come from the layout placeholders, not freestanding text boxes.", + "excerpt_sha256": "0b310f0c00fa47e1e26e37b534efe3db360ec23dfe3636efc8a9c55b3f2a552d" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the \"Title Slide\" layout — the title and subtitle MUST come from the layout placeholders, not freestanding text boxes.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Title text (in the title placeholder):", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Title text** (in the title placeholder):", + "excerpt_sha256": "8c4bb16fd76b9e1f1865bae574649a37f0971844ab53077520c6ea4c2f309ca2" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title text (in the title placeholder):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Title text:\n AcidSlide v1", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 15, + "excerpt": " ```\n AcidSlide v1\n ```", + "excerpt_sha256": "7bdd5f801459c4d38cc02232b37ee74b3a2cc304bc04c6845c881ee88beb98cb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Title text:\n AcidSlide v1", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Subtitle text (in the subtitle placeholder):", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": "3. **Subtitle text** (in the subtitle placeholder):", + "excerpt_sha256": "dbf6bf9e79cec9946747ca55b6bcd9f1334927e2a3259244adb181de39483b88" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Subtitle text (in the subtitle placeholder):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Subtitle text:\n Benchmark for Slide Generation Fidelity", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 20, + "excerpt": " ```\n Benchmark for Slide Generation Fidelity\n ```", + "excerpt_sha256": "9fb68f3398222522e33c988721029af651a57798692f69d1323af269d597dce0" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Subtitle text:\n Benchmark for Slide Generation Fidelity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Place `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Keep that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is exactly the slide's right edge.", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": "4. **Hero image**: Place `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Keep that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is exactly the slide's right edge.", + "excerpt_sha256": "bf92f51fe54cce8d25ea88a85f3a083a359218d975fe0db85d834551bce8ea0c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Place `benchmark/assets/mirrored/hero-abstract.png` at x=18.867cm, y=2cm in a 15cm-wide frame whose height is proportional to the uncropped image. Keep that frame fixed, then crop 20% from the source image's left edge. The frame's right edge is exactly the slide's right edge.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Hero image: The image should overlap with decorative shapes (see below)", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " - The image should overlap with decorative shapes (see below)", + "excerpt_sha256": "ddc4a7e86bf4a6d9ef4aacf8c67af5cd8f522a79bf92aaaae098424e1a137522" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Hero image: The image should overlap with decorative shapes (see below)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Decorative shapes (3 overlapping rounded rectangles):", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": "5. **Decorative shapes** (3 overlapping rounded rectangles):", + "excerpt_sha256": "439fdb7e1912fbb44963deb4029c474ea20c6c8eef2d7e2f41eadad57dce0925" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative shapes (3 overlapping rounded rectangles):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Decorative shapes: Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": " - Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline", + "excerpt_sha256": "ceb38449d9b4c62357a19102361670e1ad1f31bd24b63dbcfe7741910173dc68" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative shapes: Rectangle A: 8cm × 8cm, position (14cm, 4cm), fill `#2AACB8` at 40% opacity, corner radius 0.5cm, NO outline", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Decorative shapes: Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": " - Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline", + "excerpt_sha256": "eb3715214a4cdd002fbd36318f0cdaab96d4ad1d948710342890f960dfe7e586" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative shapes: Rectangle B: 6cm × 10cm, position (18cm, 1cm), fill `#E8634A` at 30% opacity, corner radius 0.5cm, NO outline", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Decorative shapes: Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " - Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline", + "excerpt_sha256": "8121f5c08926e60778144076e5a58bf8f53b46fb90486296c8f9d2ffdc30d17c" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative shapes: Rectangle C: 10cm × 6cm, position (16cm, 8cm), fill `#D4A843` at 25% opacity, corner radius 0.5cm, NO outline", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Z-order (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": "6. **Z-order** (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text", + "excerpt_sha256": "5f6d9694c8f83ca450ceb053c4ec0f6fb4d91497a4cfb601af06964744e5749e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Z-order (bottom to top): Master background → Rectangle C → Rectangle A → Hero image → Rectangle B → Title text → Subtitle text", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Apply a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm.", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": "7. **Shadow**: Apply a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm.", + "excerpt_sha256": "d0ba57b790433b0b40850a8b2baabab10cbd928262f8bd38e4886dbdc99b1951" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Apply a soft outer shadow to the hero image: color `#000000` at 40% opacity, offset 3mm down and 2mm right, blur 5mm.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-01.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "must come from the master's slide number placeholder (do NOT type \"1\" manually).", + "provenance": { + "source_id": "slide-01-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": "8. **Slide number**: must come from the master's slide number placeholder (do NOT type \"1\" manually).", + "excerpt_sha256": "e3523528958f33cfb018f2cb3008876218cb68378bf14aab0e4be5c2674690b0" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "must come from the master's slide number placeholder (do NOT type \"1\" manually).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 1 + }, + { + "requirement_id": "slide-02.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\" (from master)", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\" (from master)", + "excerpt_sha256": "d5ff270dfcb988e148b84bc334067d7180432e669aa665b24cdd7991c203ef92" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the \"Content Slide\" layout. Title and body MUST be in the layout placeholders.", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. Use the \"Content Slide\" layout. Title and body MUST be in the layout placeholders.", + "excerpt_sha256": "017fa588ab5ee20a6d31153a1a1036a5807f206d6579b142224e470dca43ed08" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the \"Content Slide\" layout. Title and body MUST be in the layout placeholders.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `Agenda`", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Title** (placeholder): `Agenda`", + "excerpt_sha256": "bc59839ca3e1dfb679872032188f0ba367a561ddecb1db307316b01725c2d4d6" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `Agenda`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Body (placeholder) — a bulleted list with specific formatting:", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": "3. **Body** (placeholder) — a bulleted list with specific formatting:", + "excerpt_sha256": "fae33ae4802620458159d7690e31c2c2898e8befb3bf2f67dd32839d4e0440a4" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body (placeholder) — a bulleted list with specific formatting:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Body:\n • Opening Remarks\n ◦ Welcome and introductions\n ◦ Safety briefing\n • Technical Deep Dive\n ◦ Architecture overview\n ◦ Performance benchmarks\n ◦ Security audit results\n • Breakout Sessions\n ◦ Track A: Infrastructure\n ◦ Track B: Applications\n • Closing & Next Steps", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 27, + "excerpt": " ```\n • Opening Remarks\n ◦ Welcome and introductions\n ◦ Safety briefing\n • Technical Deep Dive\n ◦ Architecture overview\n ◦ Performance benchmarks\n ◦ Security audit results\n • Breakout Sessions\n ◦ Track A: Infrastructure\n ◦ Track B: Applications\n • Closing & Next Steps\n ```", + "excerpt_sha256": "96b03fc8386024ba6b1a514e1141915e1205bbba503750bb3559535de0301cde" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Body:\n • Opening Remarks\n ◦ Welcome and introductions\n ◦ Safety briefing\n • Technical Deep Dive\n ◦ Architecture overview\n ◦ Performance benchmarks\n ◦ Security audit results\n • Breakout Sessions\n ◦ Track A: Infrastructure\n ◦ Track B: Applications\n • Closing & Next Steps", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Body: Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A`", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A`", + "excerpt_sha256": "19a9f982259b052c1c0b6483cdae99a37d597127c7378371eb06fb80194397a4" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body: Level 1 bullets (•): Liberation Sans 18pt Bold, `#E8634A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Body: Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE`", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": " - Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE`", + "excerpt_sha256": "8698a2581971b2e0ffdc0b964fe079d11441f34c68fe1fdebebd555f7f0bb583" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body: Level 2 bullets (◦): Liberation Sans 14pt Regular, `#F5F3EE`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Body: Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm", + "excerpt_sha256": "596a126c0bc6067e1e76a52490cf61bc7a771fe36a62e5d1cd77d2a4980f8ffc" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body: Bullet indent: Level 1 = 0.5cm, Level 2 = 1.5cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Body: Line spacing: 1.2× for Level 1, 1.0× for Level 2", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - Line spacing: 1.2× for Level 1, 1.0× for Level 2", + "excerpt_sha256": "73f672037a5f0f92c8bf3f9f44e4f1f951c802f0316ab099d64d582de45b0c36" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body: Line spacing: 1.2× for Level 1, 1.0× for Level 2", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Body: Paragraph spacing: 6pt after each Level 1 item", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Paragraph spacing: 6pt after each Level 1 item", + "excerpt_sha256": "35c1783f5a93ad5c3a0354847e6acd51e5c746a13539a46b2b3c1839ca6cd4b7" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body: Paragraph spacing: 6pt after each Level 1 item", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Use native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs.", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " Use native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs.", + "excerpt_sha256": "990b5f2ad05d6d97200a6f042293f9154c8fcc5fea7b9aa83411a2416065fef8" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use native paragraph-bullet properties. The shown `•` and `◦` characters specify the required bullet glyphs and are not literal characters in the paragraph text runs.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Create three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored.", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 37, + "line_end": 37, + "excerpt": "4. **Grouped icon-text rows**: Create three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored.", + "excerpt_sha256": "2c08c046ed06392b5e7aeffbf2b7df7ca4cf7467377e284ea27e3eb2bfc3437a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Create three icon-text rows on the right. Each row contains one 1cm teal circle and one time label. Put all six leaf objects directly in one flat group; do not create row subgroups. Align the group's top to the first bullet and bottom to the last bullet. Exact horizontal position and the two intermediate row gaps are intentionally unconstrained and unscored.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Grouped icon-text rows: The three time labels, from top to bottom, are \"09:00\", \"11:30\", and \"14:00\" in Liberation Sans 14pt Bold `#FFFFFF`.", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": " - The three time labels, from top to bottom, are \"09:00\", \"11:30\", and \"14:00\" in Liberation Sans 14pt Bold `#FFFFFF`.", + "excerpt_sha256": "bf142009ffc266c0c889c9e0832e2fefc0bea28fbb2730a35c551fa210865312" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Grouped icon-text rows: The three time labels, from top to bottom, are \"09:00\", \"11:30\", and \"14:00\" in Liberation Sans 14pt Bold `#FFFFFF`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-02.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Grouped icon-text rows: Each circle is filled with `#2AACB8`.", + "provenance": { + "source_id": "slide-02-prompt", + "source_type": "prompt", + "line_start": 39, + "line_end": 39, + "excerpt": " - Each circle is filled with `#2AACB8`.", + "excerpt_sha256": "4b0fc6ed11197c68e71b57017bf5e4beb5a7d2856a8da7868a2b7369e1498055" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Grouped icon-text rows: Each circle is filled with `#2AACB8`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 2 + }, + { + "requirement_id": "slide-03.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Blank with Footer\" (from master)", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Blank with Footer\" (from master)", + "excerpt_sha256": "a01108d9aa4a38679a98a731881f3e6f50a529d98b0ad70d68b9e967e08af0ae" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Blank with Footer\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Title text box (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders):", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Title text box** (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders):", + "excerpt_sha256": "2c53286ed72191a3933e2d5994503bfbc111b2e408f2d6245001d85ac0edf642" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title text box (freestanding, NOT a placeholder — this slide uses Layout 4 which has no content placeholders):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Title text box: Text: `Performance Metrics`", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": " - Text: `Performance Metrics`", + "excerpt_sha256": "60b3166bd7d181388c0780d2d0934afc79de32d19a3231e83c4e29231d4a124e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title text box: Text: `Performance Metrics`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Title text box: Font: Carlito 36pt Bold, `#FFFFFF`", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": " - Font: Carlito 36pt Bold, `#FFFFFF`", + "excerpt_sha256": "db886f12f57da3ee4aba71dc855f05cb6ed0083426cf5cf3195908ccc688bca9" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title text box: Font: Carlito 36pt Bold, `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Title text box: Position: x=1.5cm, y=0.8cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": " - Position: x=1.5cm, y=0.8cm", + "excerpt_sha256": "4b7ffae6f97fab9e631bf555264cfc675cb4437f916195e5e19c310a312f5765" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title text box: Position: x=1.5cm, y=0.8cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Native table — this MUST be a real LibreOffice Impress table, not shapes pretending to be a table:", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": "2. **Native table** — this MUST be a real LibreOffice Impress table, not shapes pretending to be a table:", + "excerpt_sha256": "ca6f72656f10092c16d7e747fe7b84ae5eab98ac1366f98547da94e5d53c5d66" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native table — this MUST be a real LibreOffice Impress table, not shapes pretending to be a table:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Native table: Position: x=1.5cm, y=3cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " - Position: x=1.5cm, y=3cm", + "excerpt_sha256": "d28c5de5018a5beb75e2a8b1d2599ffdfa96f0d7c62243d98ce8fe1a0867a2ef" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native table: Position: x=1.5cm, y=3cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Native table: Size: 30cm × 12cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " - Size: 30cm × 12cm", + "excerpt_sha256": "d1eb292873ce6a9024ac85e0da7f838a70ec603a0782246024f057f122965be4" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native table: Size: 30cm × 12cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Native table: Rows: 7 (1 header + 6 data)", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": " - Rows: 7 (1 header + 6 data)", + "excerpt_sha256": "ebd17b1c7ba1f46017438a30fd3d7016ed5014928e904dffaef4fe10399cac02" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native table: Rows: 7 (1 header + 6 data)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Native table: Columns: 5", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " - Columns: 5", + "excerpt_sha256": "df0383116804548e9a2606703a370122167def1768c530e033fddb63f40ce9ca" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native table: Columns: 5", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Use this exact table header row: | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 21, + "line_end": 21, + "excerpt": " | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target |", + "excerpt_sha256": "274f0c8e8a2ad1fb7b04aa071f4a957673176e28daa3d197954dc8f714d28f3b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this exact table header row: | Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms |", + "excerpt_sha256": "8bd46764e45c723b1d2c177519e11829a1506db9e6346dc3dab48a8a19cd0ca9" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Latency (p50) | 12ms | 11ms | 9ms | ≤10ms |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms |", + "excerpt_sha256": "ae9ded9140388599a2efc2ae4082f37266d025f5715caae6303d2045bd70357f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Latency (p99) | 89ms | 72ms | 58ms | ≤75ms |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps |", + "excerpt_sha256": "5d2fd972abe4a1b2e8c8149b32f4d9c365ce5b47907ad99fada96e65f72a5747" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Throughput | 1,200 rps | 1,450 rps | 1,890 rps | ≥2,000 rps |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": " | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% |", + "excerpt_sha256": "0d4bd1967a4c8e5386a9bd5a79eeaddab4fbc20d76ede1c4f9044963d9860f9e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Error Rate | 0.12% | 0.08% | 0.04% | ≤0.05% |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": " | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% |", + "excerpt_sha256": "3f3c3a2f6a67849d90da50e5c7de828ea27fb3f947adb87ce1ea776322895523" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Uptime | 99.91% | 99.95% | 99.98% | ≥99.95% |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Cache Hit | 72% | 78% | 84% | ≥80% |", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " | Cache Hit | 72% | 78% | 84% | ≥80% |", + "excerpt_sha256": "a024a0b7ee91f922a3cf8ed78d0acb0474b5da89be9dc59d85931a6c898af4a8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Metric / Q1 2024 / Q2 2024 / Q3 2024 / Target: Use this exact table data row: | Cache Hit | 72% | 78% | 84% | ≥80% |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered", + "excerpt_sha256": "20ba4aa5364ec4d836c6be39959f41b1c690fb7e2feceb3ac9dddf1f411100d6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Header row: background `#1B2A4A`, text Carlito 14pt Bold `#FFFFFF`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Data rows: alternating `#0F1923` and `#161F2E`", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - Data rows: alternating `#0F1923` and `#161F2E`", + "excerpt_sha256": "b81993df5b5dc7b61c9e7fb4f8cc21c472f88d229334af97d1115d6cb9ca83ca" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Data rows: alternating `#0F1923` and `#161F2E`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for \"Metric\", centered for all others", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for \"Metric\", centered for all others", + "excerpt_sha256": "9efe69002b4507bf01010f1c8754789a4601391632a2155e3ffaa18dc7f6c2bd" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Data text: Liberation Sans 14pt, `#F5F3EE`, left-aligned for \"Metric\", centered for all others", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Cell padding: 0.3cm on all sides", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " - Cell padding: 0.3cm on all sides", + "excerpt_sha256": "c62fec42812f6dc2271bac7bd18468fc170775885eaae9755dc44ca3fdcb6738" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Cell padding: 0.3cm on all sides", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` below header row", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` below header row", + "excerpt_sha256": "98c3575a3c649320eae3658665696b20798404ee0f41ceb97e57ac96e2bf41ce" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Borders: 0.5pt `#2AACB8` between all cells, 2pt `#2AACB8` below header row", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r023", + "scope": "slide", + "mandatory": true, + "statement": "Table styling: Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold.", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold.", + "excerpt_sha256": "808ae206e3ceb8be4d5e3cd5741370bc7efdf12e4f42d6a03a144ada9938a3c7" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Table styling: Q3 column: color each Q3 value `#2AACB8` when it meets the Target-column threshold and `#E8634A` when it misses that threshold.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r024", + "scope": "slide", + "mandatory": true, + "statement": "Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓)", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 37, + "line_end": 37, + "excerpt": " - Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓)", + "excerpt_sha256": "d328aff4f68fe9ee3213c64e50cd02e1cdde3617dbba250d5e2e76ff20a7f87b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Q3: Latency p50 (9 ≤ 10 ✓), p99 (58 ≤ 75 ✓), Throughput (1890 misses 2000 ✗), Error (0.04 ≤ 0.05 ✓), Uptime (99.98 ≥ 99.95 ✓), Cache (84 ≥ 80 ✓)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r025", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout — a rounded rectangle with text, positioned next to the table:", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 39, + "line_end": 39, + "excerpt": "3. **Annotation callout** — a rounded rectangle with text, positioned next to the table:", + "excerpt_sha256": "058264ac1c57ad970470126824554326e0cb13d93de64fc02786b18d33184ae4" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout — a rounded rectangle with text, positioned next to the table:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r026", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: Position: x=24cm, y=15.5cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 40, + "line_end": 40, + "excerpt": " - Position: x=24cm, y=15.5cm", + "excerpt_sha256": "f5027ee458f32ee916f4f8b95aed570c43772d4d8e6505e6a9876cd3e28f6721" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: Position: x=24cm, y=15.5cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r027", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: Size: 8cm × 2.5cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 41, + "line_end": 41, + "excerpt": " - Size: 8cm × 2.5cm", + "excerpt_sha256": "f10824e7041079966e819d4c4fa332a89a0b89e0533dd7a2964ecd6bf99a0f45" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: Size: 8cm × 2.5cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r028", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: Fill: `#E8634A`", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 42, + "line_end": 42, + "excerpt": " - Fill: `#E8634A`", + "excerpt_sha256": "05a1b05c782fb67f1d56f4b96ab8db9f80626b11ab2de8a40ccc171a5ca6939d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: Fill: `#E8634A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r029", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: Corner radius: 0.3cm", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 43, + "line_end": 43, + "excerpt": " - Corner radius: 0.3cm", + "excerpt_sha256": "7ea12cd9fac64c665c5348fb0bf2eccd7eb8ceb3aa2fa5d815926239b2726594" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: Corner radius: 0.3cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r030", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: Text: \"Throughput target\\nmissed by 5.5%\" in Liberation Sans 12pt Bold `#FFFFFF`, centered", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 44, + "line_end": 44, + "excerpt": " - Text: \"Throughput target\\nmissed by 5.5%\" in Liberation Sans 12pt Bold `#FFFFFF`, centered", + "excerpt_sha256": "d0cff3ed1ce18de96dcd16ab23102989b76fb6cea548b3195e55b7df15e5a616" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: Text: \"Throughput target\\nmissed by 5.5%\" in Liberation Sans 12pt Bold `#FFFFFF`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r031", + "scope": "slide", + "mandatory": true, + "statement": "Annotation callout: A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained.", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 45, + "line_end": 45, + "excerpt": " - A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained.", + "excerpt_sha256": "b2d88e6a21b1ea53a69bee034a0ac795c04a9ce5a36badf2f0843e632e68eb99" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Annotation callout: A thin line (1pt, `#E8634A`) connecting the callout to the Q3 Throughput cell; connector routing is otherwise unconstrained.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-03.prompt-r032", + "scope": "slide", + "mandatory": true, + "statement": "the Metric-column paragraphs must use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required.", + "provenance": { + "source_id": "slide-03-prompt", + "source_type": "prompt", + "line_start": 47, + "line_end": 47, + "excerpt": "4. **Paragraph indent**: the Metric-column paragraphs must use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required.", + "excerpt_sha256": "f6d2b3aae55507b015937752553dd4fc823ded14b8046914f79e326d283f522c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "the Metric-column paragraphs must use a 0.5cm left paragraph indent in addition to cell padding. No tab character or tab-stop property is required.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 3 + }, + { + "requirement_id": "slide-04.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\" (from master)", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\" (from master)", + "excerpt_sha256": "d5ff270dfcb988e148b84bc334067d7180432e669aa665b24cdd7991c203ef92" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `Revenue Growth`", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Title** (placeholder): `Revenue Growth`", + "excerpt_sha256": "0b120fe9f45fb17834a7b13c1875affbc71f92e368b85ce05751d636108286ed" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `Revenue Growth`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Native chart — MUST be a real LibreOffice Impress chart, not shapes/images:", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Native chart** — MUST be a real LibreOffice Impress chart, not shapes/images:", + "excerpt_sha256": "ab856ada71ae17c0ec8614fee83b442755ef2a9ebcd25880a2b72fc434d55346" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native chart — MUST be a real LibreOffice Impress chart, not shapes/images:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Native chart: Chart type: Clustered bar chart (horizontal bars)", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": " - Chart type: **Clustered bar chart** (horizontal bars)", + "excerpt_sha256": "d862bd3b22d52886eb0e46e5a0d94bad2f309b0bbbb14c0a5970a94894d43017" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native chart: Chart type: Clustered bar chart (horizontal bars)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Native chart: Position: x=1.5cm, y=3cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": " - Position: x=1.5cm, y=3cm", + "excerpt_sha256": "d28c5de5018a5beb75e2a8b1d2599ffdfa96f0d7c62243d98ce8fe1a0867a2ef" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native chart: Position: x=1.5cm, y=3cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Native chart: Size: 20cm × 14cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": " - Size: 20cm × 14cm", + "excerpt_sha256": "93a0527e5b686fb2bd5cdae09d66512ea2a2f2401ec6d5c8dcfe172e539a3f05" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Native chart: Size: 20cm × 14cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Use this exact table header row: | Region | 2023 Revenue ($M) | 2024 Revenue ($M) |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " | Region | 2023 Revenue ($M) | 2024 Revenue ($M) |", + "excerpt_sha256": "c7897e54061256f4145fc988b0443610519d3462b70e85d9f5dfb832e623bec6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this exact table header row: | Region | 2023 Revenue ($M) | 2024 Revenue ($M) |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | North America | 42.3 | 51.8 |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 21, + "line_end": 21, + "excerpt": " | North America | 42.3 | 51.8 |", + "excerpt_sha256": "44d43c03d455f35922c61ab52ba656a4a34a30ca299f84bffb8221123d6eb102" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | North America | 42.3 | 51.8 |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Europe | 28.7 | 35.2 |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": " | Europe | 28.7 | 35.2 |", + "excerpt_sha256": "fc9acdcc5e655c82b1d0385b942333292244bdc02db7381ef53a5d671995f059" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Europe | 28.7 | 35.2 |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Asia Pacific | 19.4 | 31.6 |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " | Asia Pacific | 19.4 | 31.6 |", + "excerpt_sha256": "6f1ba0228b03b88b0f6db9751d113015916def9599f13dbb0ff0f5281b78b105" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Asia Pacific | 19.4 | 31.6 |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Latin America | 8.1 | 12.4 |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " | Latin America | 8.1 | 12.4 |", + "excerpt_sha256": "bcc321cc7c8c8c818f8560d7e5f03624ecefa1f2724e05e2f333ef2654ebf72d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Latin America | 8.1 | 12.4 |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Middle East & Africa | 3.9 | 7.2 |", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " | Middle East & Africa | 3.9 | 7.2 |", + "excerpt_sha256": "ae82399810db445ffca68564ed372a293a58106dfabe51151dd76e02fa2ceba9" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Region / 2023 Revenue ($M) / 2024 Revenue ($M): Use this exact table data row: | Middle East & Africa | 3.9 | 7.2 |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: 2023 bars: `#1B2A4A` (navy)", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " - 2023 bars: `#1B2A4A` (navy)", + "excerpt_sha256": "c1706c9291de8eb7542fdc778145b84af28650edf3b012719528821c11893c09" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: 2023 bars: `#1B2A4A` (navy)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: 2024 bars: `#E8634A` (coral)", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - 2024 bars: `#E8634A` (coral)", + "excerpt_sha256": "7bab1e4195c22d7e02ac6f7e4a8b697706790fbacc95a1e095c8d3a26e96c255" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: 2024 bars: `#E8634A` (coral)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: Chart title: \"Annual Revenue by Region\" in Carlito 16pt Bold", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": " - Chart title: \"Annual Revenue by Region\" in Carlito 16pt Bold", + "excerpt_sha256": "092de9e32452e963c93c198986e6ade8e2bc7d73ec97c20519bff033b502e01d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: Chart title: \"Annual Revenue by Region\" in Carlito 16pt Bold", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`.", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`.", + "excerpt_sha256": "dec24dfc7b49ee1bf42baad62a33617422f4a202db14bc2eed880af392f64566" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: X-axis value labels: Liberation Sans 11pt, `#2D2D2D`, format `$0M`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`.", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`.", + "excerpt_sha256": "97142e8d8023682784bfab8a66787985264fb2a4a5d3ce42134868b60813c188" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: Y-axis category labels: Liberation Sans 12pt, `#2D2D2D`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: Legend: bottom of chart, Liberation Sans 11pt", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Legend: bottom of chart, Liberation Sans 11pt", + "excerpt_sha256": "14ed942da2f097b441814ed414f28704da11d741b0ba17ee49f76e8f257b2d97" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: Legend: bottom of chart, Liberation Sans 11pt", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt.", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " - Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt.", + "excerpt_sha256": "573bf9b2b8380ada20996eef2de398de0242106f477876f975d0122647f74547" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: Gridlines: vertical major-value gridlines only, `#E0E0E0` 0.5pt.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: No chart border", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - No chart border", + "excerpt_sha256": "f42ab75ca0956f768fedbceb77352c88a19522ec668c6e05e8323600cf774f57" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: No chart border", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "Chart formatting: Background: transparent (slide background shows through)", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - Background: transparent (slide background shows through)", + "excerpt_sha256": "f8c8612057cd0ede3c3a5b0c5685d97bdf8112a199597eb673466c6cfcb0d894" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Chart formatting: Background: transparent (slide background shows through)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "Callout shapes — two overlaid callout annotations:", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": "3. **Callout shapes** — two overlaid callout annotations:", + "excerpt_sha256": "44587bc3790332e8d7a438cc2ae0010119d672a1384cfeaa4417397ffd47c6aa" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout shapes — two overlaid callout annotations:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r023", + "scope": "slide", + "mandatory": true, + "statement": "Callout shapes: Callout 1: positioned over the \"Asia Pacific 2024\" bar", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 40, + "line_end": 40, + "excerpt": " - Callout 1: positioned over the \"Asia Pacific 2024\" bar", + "excerpt_sha256": "738e09f4efcfb91e61c6d4bc70987a39ea759eb9f343dd4f5753ab1784875971" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout shapes: Callout 1: positioned over the \"Asia Pacific 2024\" bar", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r024", + "scope": "slide", + "mandatory": true, + "statement": "Rounded rectangle, 5cm × 2cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 41, + "line_end": 41, + "excerpt": " - Rounded rectangle, 5cm × 2cm", + "excerpt_sha256": "501781913280b4043255b39768ee56b34362203d32fb6a59f764f10e6bdf65ee" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Rounded rectangle, 5cm × 2cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r025", + "scope": "slide", + "mandatory": true, + "statement": "Fill: `#2AACB8`", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 42, + "line_end": 42, + "excerpt": " - Fill: `#2AACB8`", + "excerpt_sha256": "9a642d3241d09f6b812a0c5d12b58130769f01e3100809e913a22a55ef161607" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Fill: `#2AACB8`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r026", + "scope": "slide", + "mandatory": true, + "statement": "Text: \"+62.9% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 43, + "line_end": 43, + "excerpt": " - Text: \"+62.9% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "excerpt_sha256": "613faef1a52c4a97b36bc8ef0561dcc600827e8c6bab7699cbb9907cb4c0ee5c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Text: \"+62.9% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r027", + "scope": "slide", + "mandatory": true, + "statement": "Arrow connector pointing from callout to the bar", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 44, + "line_end": 44, + "excerpt": " - Arrow connector pointing from callout to the bar", + "excerpt_sha256": "c3f47595a3bf4431556df0243219cf826315059d7850f8ac1aa4589beabb51ea" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Arrow connector pointing from callout to the bar", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r028", + "scope": "slide", + "mandatory": true, + "statement": "Callout shapes: Callout 2: positioned over the \"Middle East & Africa 2024\" bar", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 46, + "line_end": 46, + "excerpt": " - Callout 2: positioned over the \"Middle East & Africa 2024\" bar", + "excerpt_sha256": "2ec8771a87023dad7a137287ae5e70363b419b3c83cd0805b0c594131881bb6e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout shapes: Callout 2: positioned over the \"Middle East & Africa 2024\" bar", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r029", + "scope": "slide", + "mandatory": true, + "statement": "Rounded rectangle, 5cm × 2cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 47, + "line_end": 47, + "excerpt": " - Rounded rectangle, 5cm × 2cm", + "excerpt_sha256": "501781913280b4043255b39768ee56b34362203d32fb6a59f764f10e6bdf65ee" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Rounded rectangle, 5cm × 2cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r030", + "scope": "slide", + "mandatory": true, + "statement": "Fill: `#D4A843`", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 48, + "line_end": 48, + "excerpt": " - Fill: `#D4A843`", + "excerpt_sha256": "6edf5e1d7b4dbab35b27d55dd93250d6eeafcde5610e36b4f2916b79fff898c1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Fill: `#D4A843`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r031", + "scope": "slide", + "mandatory": true, + "statement": "Text: \"+84.6% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 49, + "line_end": 49, + "excerpt": " - Text: \"+84.6% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "excerpt_sha256": "eebdb8d0d2653645a5d8b749fe83b76a1a415ef9b6254788a5b92d98847f5ceb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Text: \"+84.6% YoY\" in Liberation Sans 14pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r032", + "scope": "slide", + "mandatory": true, + "statement": "Arrow connector pointing from callout to the bar", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 50, + "line_end": 50, + "excerpt": " - Arrow connector pointing from callout to the bar", + "excerpt_sha256": "c3f47595a3bf4431556df0243219cf826315059d7850f8ac1aa4589beabb51ea" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Arrow connector pointing from callout to the bar", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r033", + "scope": "slide", + "mandatory": true, + "statement": "Supporting text block to the right of the chart:", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 52, + "line_end": 52, + "excerpt": "4. **Supporting text block** to the right of the chart:", + "excerpt_sha256": "85260fedfce0e3518017c9846a2e4fa93b544c9c2c76c9dd00af6ca9ec9206e5" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Supporting text block to the right of the chart:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r034", + "scope": "slide", + "mandatory": true, + "statement": "Supporting text block: Position: x=23cm, y=4cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 53, + "line_end": 53, + "excerpt": " - Position: x=23cm, y=4cm", + "excerpt_sha256": "5e5ada8a7a7794278594fe4442bfe85ff9b603a44124ed6a549a83ac12738948" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Supporting text block: Position: x=23cm, y=4cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r035", + "scope": "slide", + "mandatory": true, + "statement": "Supporting text block: Width: 9cm", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 54, + "line_end": 54, + "excerpt": " - Width: 9cm", + "excerpt_sha256": "94d99ae14f443ccf3b276cd393d81d57aed3d186c80021d1ab501309cf551df3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Supporting text block: Width: 9cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r036", + "scope": "slide", + "mandatory": true, + "statement": "Supporting text block: Text (Liberation Sans 14pt, `#F5F3EE`):", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 55, + "line_end": 55, + "excerpt": " - Text (Liberation Sans 14pt, `#F5F3EE`):", + "excerpt_sha256": "8f9c07b25debf60404390751f3f6079a41f17f07d97ed4cf986d5456c580fd4a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Supporting text block: Text (Liberation Sans 14pt, `#F5F3EE`):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-04.prompt-r037", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Supporting text block:\n Key Takeaways:\n \n ▸ Total revenue up 38.2% YoY\n ▸ APAC fastest-growing region\n ▸ All regions exceeded targets", + "provenance": { + "source_id": "slide-04-prompt", + "source_type": "prompt", + "line_start": 56, + "line_end": 62, + "excerpt": " ```\n Key Takeaways:\n \n ▸ Total revenue up 38.2% YoY\n ▸ APAC fastest-growing region\n ▸ All regions exceeded targets\n ```", + "excerpt_sha256": "dce1c4edf3ca225261a4cfc043ca4f4856c1615381c335d3f65ba6ed35e7b168" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Supporting text block:\n Key Takeaways:\n \n ▸ Total revenue up 38.2% YoY\n ▸ APAC fastest-growing region\n ▸ All regions exceeded targets", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 4 + }, + { + "requirement_id": "slide-05.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\" (from master)", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\" (from master)", + "excerpt_sha256": "d5ff270dfcb988e148b84bc334067d7180432e669aa665b24cdd7991c203ef92" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied.", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied.", + "excerpt_sha256": "427d91aac6ed7507ef66f5b7bd43d9b293e8103452535d1a7945f3c61c4c3b49" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "This slide's purpose is to verify that the master/layout is being used correctly, not just visually copied.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `Our Team`", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "1. **Title** (placeholder): `Our Team`", + "excerpt_sha256": "d276296b14fca29a4dfece0dd4f8fa6b4e20f322098d9ea569c4a6cf612bc1d0" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `Our Team`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Body content — three team member cards arranged horizontally:", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": "2. **Body content** — three team member cards arranged horizontally:", + "excerpt_sha256": "119beb1abca34956efdb8cb591ddafb32147d842a5fdb77aa67ecb07f6363260" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content — three team member cards arranged horizontally:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Each card is a group containing:", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " Each card is a group containing:", + "excerpt_sha256": "3ee12212dafa41646581eaedbecc77a0818c3fc59484792e6ec376aefc8880d5" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Each card is a group containing:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Body content: A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8`", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " - A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8`", + "excerpt_sha256": "33fbd9d856f486ae86889cb547e878b9637738e25d1758dcffbae3cb9919b7f5" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content: A rounded rectangle: 9cm × 13cm, fill `#161F2E`, corner radius 0.3cm, border 1pt `#2AACB8`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Body content: Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text \"Photo\" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": " - Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text \"Photo\" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos", + "excerpt_sha256": "758f3edc588a58cc4f16c2a1cf7890d0073560c3cd0242e5fc796eacecc3ad29" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content: Circle placeholder for photo: 4cm diameter, centered at top of card, fill `#1B2A4A` with text \"Photo\" in center (Liberation Sans 12pt `#FFFFFF`) — since we have no actual photos", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Body content: Name: Carlito 18pt Bold `#FFFFFF`, centered", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " - Name: Carlito 18pt Bold `#FFFFFF`, centered", + "excerpt_sha256": "f54eb0aaa878cb709c7ae64d60c9b37a1be8e3fbeb1eea5bcc4d7f40d8e2e7ae" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content: Name: Carlito 18pt Bold `#FFFFFF`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Body content: Title: Liberation Sans 14pt `#E8634A`, centered", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 20, + "line_end": 20, + "excerpt": " - Title: Liberation Sans 14pt `#E8634A`, centered", + "excerpt_sha256": "934c146a9e3e7ae2fc4e28bbc54c4aaac5fb8f4f12489473293d29577cb72156" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content: Title: Liberation Sans 14pt `#E8634A`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Body content: Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 21, + "line_end": 21, + "excerpt": " - Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines", + "excerpt_sha256": "4f3fa1b74ddba0091fa8ca001212a3e11f0c5907c26a7815777e50d042abfbc1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Body content: Description: Liberation Sans 12pt `#F5F3EE`, centered, max 3 lines", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Card 1: Name: \"Sarah Chen\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " - Name: \"Sarah Chen\"", + "excerpt_sha256": "76f8e0c26ed82527396758c54f32052e86f2edd7f7c1266b16fc4a20c4425e82" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 1: Name: \"Sarah Chen\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Card 1: Title: \"Chief Architect\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " - Title: \"Chief Architect\"", + "excerpt_sha256": "69aa3530bfd1ce2cdf7baaeed3388d1fc67e49d38c54a77689950bcc28fa0fc0" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 1: Title: \"Chief Architect\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Card 1: Description: \"15 years building distributed systems at scale\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": " - Description: \"15 years building distributed systems at scale\"", + "excerpt_sha256": "19a67c00926d22b08a47f12c04f44808158a9a6f14c55c951a0ad790b0f49599" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 1: Description: \"15 years building distributed systems at scale\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Card 2: Name: \"Marcus Rivera\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - Name: \"Marcus Rivera\"", + "excerpt_sha256": "bd39d60d9545874594695f73698f699c1757c25a49e8a86df24232e5d6aeb859" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 2: Name: \"Marcus Rivera\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Card 2: Title: \"Head of Design\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": " - Title: \"Head of Design\"", + "excerpt_sha256": "61e10e134c769379eb48c31f2cf2cb812dcd6c2f8e4357de5727d066e164cdec" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 2: Title: \"Head of Design\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Card 2: Description: \"Formerly at Apple, obsessed with pixel-perfect interfaces\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - Description: \"Formerly at Apple, obsessed with pixel-perfect interfaces\"", + "excerpt_sha256": "31024ab5990374b2d08d48ca11520525a00104d291518656aec393c2d3c48dbc" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 2: Description: \"Formerly at Apple, obsessed with pixel-perfect interfaces\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Card 3: Name: \"Yuki Tanaka\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " - Name: \"Yuki Tanaka\"", + "excerpt_sha256": "7a8b851d3ccd4ceb7970d812653ac6627312c64e6a15c2f2704dfe2393c647b5" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 3: Name: \"Yuki Tanaka\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Card 3: Title: \"ML Engineering Lead\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - Title: \"ML Engineering Lead\"", + "excerpt_sha256": "af3a4b5f862ab8de44fb1c2ac41e0e4c34a549c4ea14200f2a78b17cac28ec8b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 3: Title: \"ML Engineering Lead\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Card 3: Description: \"PhD in NLP, built the model serving infrastructure\"", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - Description: \"PhD in NLP, built the model serving infrastructure\"", + "excerpt_sha256": "4b09a94a03d142f71aaea2216e67d944731a65a5bcebcebe27f88abed73ae1e1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card 3: Description: \"PhD in NLP, built the model serving infrastructure\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Cards positioned at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide.", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": " Cards positioned at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide.", + "excerpt_sha256": "2195b4d69778c1a220ca0cf7e7c2ba8399de246ced5051e5091eecd51b272347" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Cards positioned at x=1.5cm, x=12cm, x=22.5cm — evenly spaced across the slide.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "The bottom footer line, \"ACIDSLIDE\" text, and slide number MUST come from the master. Do NOT manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited.", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 40, + "line_end": 40, + "excerpt": "3. **Critical requirement**: The bottom footer line, \"ACIDSLIDE\" text, and slide number MUST come from the master. Do NOT manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited.", + "excerpt_sha256": "4b3be5047bc9ad3ae1bf98d898ebc6d72f21a61844ee6f88f4df5f9f66b28da8" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The bottom footer line, \"ACIDSLIDE\" text, and slide number MUST come from the master. Do NOT manually add these elements on this slide. The whole point of this slide is to test that the master is correctly inherited.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-05.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "The accent bar on the left edge must also come from the \"Content Slide\" layout, not a manually placed shape.", + "provenance": { + "source_id": "slide-05-prompt", + "source_type": "prompt", + "line_start": 42, + "line_end": 42, + "excerpt": "4. **The accent bar** on the left edge must also come from the \"Content Slide\" layout, not a manually placed shape.", + "excerpt_sha256": "3bcb602e059f6057bdd05732a3e920c686209e609c2684c3b2188a4de78ce4ce" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The accent bar on the left edge must also come from the \"Content Slide\" layout, not a manually placed shape.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 5 + }, + { + "requirement_id": "slide-06.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Blank with Footer\" (from master)", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Blank with Footer\" (from master)", + "excerpt_sha256": "a01108d9aa4a38679a98a731881f3e6f50a529d98b0ad70d68b9e967e08af0ae" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Blank with Footer\" (from master)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns side by side:", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Three text columns** side by side:", + "excerpt_sha256": "b2030492bf452dc82d91f1261b80ae82024f3406d7d43a4f67419488cde1ca78" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns side by side:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Column 1 — English (left third):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": " **Column 1 — English** (left third):", + "excerpt_sha256": "e8de8d26af250e7f1f02ca14c5d84f26d58d9c28974f114b3160153c4a849200" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column 1 — English (left third):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns: Title: \"Global Perspectives\" in Carlito 24pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": " - Title: \"Global Perspectives\" in Carlito 24pt Bold `#FFFFFF`", + "excerpt_sha256": "b796902c566543b667548bf42de953d3fae313353e8dbaf13761892909aeb094" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns: Title: \"Global Perspectives\" in Carlito 24pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns: Body (Liberation Sans 14pt `#F5F3EE`, left-aligned):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": " - Body (Liberation Sans 14pt `#F5F3EE`, left-aligned):", + "excerpt_sha256": "260e1257d0748867b7f88a5cc355be042a3d300f8b4dacc893a7a051afb2f0ed" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns: Body (Liberation Sans 14pt `#F5F3EE`, left-aligned):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Three text columns:\n The rapid advancement of language models\n has transformed how organizations approach\n document generation. From financial reports\n to marketing materials, AI-driven content\n creation is reshaping every industry.", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 21, + "excerpt": " ```\n The rapid advancement of language models\n has transformed how organizations approach\n document generation. From financial reports\n to marketing materials, AI-driven content\n creation is reshaping every industry.\n ```", + "excerpt_sha256": "008d34cf6992f5ec73c9de825385f8dd5dacab0641f2caad94a0853887c78595" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Three text columns:\n The rapid advancement of language models\n has transformed how organizations approach\n document generation. From financial reports\n to marketing materials, AI-driven content\n creation is reshaping every industry.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Column 2 — Arabic RTL (center third):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " **Column 2 — Arabic RTL** (center third):", + "excerpt_sha256": "8c6a458bf5151edb8519d5b505146ab1830a92bb706a08c888a71d555d3df08a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column 2 — Arabic RTL (center third):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns: Title: \"وجهات نظر عالمية\" in Noto Sans Arabic 24pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " - Title: \"وجهات نظر عالمية\" in Noto Sans Arabic 24pt Bold `#FFFFFF`", + "excerpt_sha256": "cfa5c1bf727bd16340ae6c2646c20c2e9daf65335380d7df0eefd38a29e3c2eb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns: Title: \"وجهات نظر عالمية\" in Noto Sans Arabic 24pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns: Body (Noto Sans Arabic 14pt `#F5F3EE`, RIGHT-to-left aligned):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " - Body (Noto Sans Arabic 14pt `#F5F3EE`, **RIGHT-to-left aligned**):", + "excerpt_sha256": "6f2eecdbca47b756f83547e4fc35c6777c7a1b9648a5df46c241144c3a55a0bb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns: Body (Noto Sans Arabic 14pt `#F5F3EE`, RIGHT-to-left aligned):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Three text columns:\n لقد أدى التقدم السريع في نماذج اللغة إلى تحويل\n كيفية تعامل المؤسسات مع إنشاء المستندات. من\n التقارير المالية إلى المواد التسويقية، يعيد إنشاء\n المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة.", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 31, + "excerpt": " ```\n لقد أدى التقدم السريع في نماذج اللغة إلى تحويل\n كيفية تعامل المؤسسات مع إنشاء المستندات. من\n التقارير المالية إلى المواد التسويقية، يعيد إنشاء\n المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة.\n ```", + "excerpt_sha256": "706071d6d610b6c546dd520d0dea49dd5c947b7d7ff5a20324735825f0431fb0" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Three text columns:\n لقد أدى التقدم السريع في نماذج اللغة إلى تحويل\n كيفية تعامل المؤسسات مع إنشاء المستندات. من\n التقارير المالية إلى المواد التسويقية، يعيد إنشاء\n المحتوى المدعوم بالذكاء الاصطناعي تشكيل كل صناعة.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Three text columns: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL.", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - **CRITICAL**: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL.", + "excerpt_sha256": "a8a20e374f6bef15d36b2246b298760c9d02478919053f6f2052cd8c1da6e313" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three text columns: This column must be set to RTL paragraph direction. The text must flow right-to-left. This is NOT just right-alignment — the paragraph direction property must be set to RTL.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Column 3 — Japanese (right third):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " **Column 3 — Japanese** (right third):", + "excerpt_sha256": "0bc0d11166634dca1ef0ca6422cee45d6ae36eee7e7ce5dfb80c0266b2eb881c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column 3 — Japanese (right third):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "CRITICAL: Title: \"グローバルな視点\" in Noto Sans CJK JP 24pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - Title: \"グローバルな視点\" in Noto Sans CJK JP 24pt Bold `#FFFFFF`", + "excerpt_sha256": "27845ffb037e8fe154c25d9ee1d9850a67e8dc05327cf9b4f4f186eaca950142" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "CRITICAL: Title: \"グローバルな視点\" in Noto Sans CJK JP 24pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "CRITICAL: Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned):", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned):", + "excerpt_sha256": "51911f2198e9e3384c2e43a288f80c4e397361c815d495fa65227e13f67e1d9e" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "CRITICAL: Body (Noto Sans CJK JP 14pt `#F5F3EE`, left-aligned):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for CRITICAL:\n 言語モデルの急速な進歩により、組織がドキュメント生成に\n 取り組む方法が変革されました。財務報告からマーケティング\n 資料まで、AI主導のコンテンツ作成はあらゆる産業を\n 再形成しています。", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 37, + "line_end": 42, + "excerpt": " ```\n 言語モデルの急速な進歩により、組織がドキュメント生成に\n 取り組む方法が変革されました。財務報告からマーケティング\n 資料まで、AI主導のコンテンツ作成はあらゆる産業を\n 再形成しています。\n ```", + "excerpt_sha256": "b1e3294b64cebdab1df79f24bca06f36a4def625848cef43a896712e2810f7e3" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for CRITICAL:\n 言語モデルの急速な進歩により、組織がドキュメント生成に\n 取り組む方法が変革されました。財務報告からマーケティング\n 資料まで、AI主導のコンテンツ作成はあらゆる産業を\n 再形成しています。", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Decorative separator lines between columns:", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 44, + "line_end": 44, + "excerpt": "2. **Decorative separator lines** between columns:", + "excerpt_sha256": "88c9f2b66cf7570757d0807a718ffd989c11f330489988caaacc946864a8f465" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative separator lines between columns:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Decorative separator lines: Vertical lines at x=11.2cm and x=22.5cm", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 45, + "line_end": 45, + "excerpt": " - Vertical lines at x=11.2cm and x=22.5cm", + "excerpt_sha256": "fed3982c4bd6bfbbd1cae44647480ca320c1ee5332ea82db25dca1854379c4c0" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative separator lines: Vertical lines at x=11.2cm and x=22.5cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Decorative separator lines: Height: from y=3cm to y=16cm", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 46, + "line_end": 46, + "excerpt": " - Height: from y=3cm to y=16cm", + "excerpt_sha256": "23a2add3058d4a620df25c26d3b3e63174b03bc8a1f20c78dc3232398cdec44d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative separator lines: Height: from y=3cm to y=16cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Decorative separator lines: Style: 1pt, `#2AACB8`, 50% opacity", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 47, + "line_end": 47, + "excerpt": " - Style: 1pt, `#2AACB8`, 50% opacity", + "excerpt_sha256": "4d0361c0b541856df8b0ede2abaa3930b3f3f3943205328160b60fdb957a0928" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Decorative separator lines: Style: 1pt, `#2AACB8`, 50% opacity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Callout box overlapping the Arabic and Japanese columns:", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 49, + "line_end": 49, + "excerpt": "3. **Callout box** overlapping the Arabic and Japanese columns:", + "excerpt_sha256": "4ad0cf2073147ebe9173c7b2c9292ed370479975e6fd5e88880138d46ee38ab8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box overlapping the Arabic and Japanese columns:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Position: x=15cm, y=13cm", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 50, + "line_end": 50, + "excerpt": " - Position: x=15cm, y=13cm", + "excerpt_sha256": "1a2ae5652df9ff82fee78a0f44165107485d8d1fb0a5731dc5132e69775b4c76" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Position: x=15cm, y=13cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Size: 12cm × 4cm", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 51, + "line_end": 51, + "excerpt": " - Size: 12cm × 4cm", + "excerpt_sha256": "16fdf6133a0c087d50823c0919773fee8d50d60705a69317c7cd6d00a98bc600" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Size: 12cm × 4cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r023", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Fill: `#E8634A` at 90% opacity", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 52, + "line_end": 52, + "excerpt": " - Fill: `#E8634A` at 90% opacity", + "excerpt_sha256": "c2672e5ad3e88c86efc7fbbd3c34059d9a6b36e9405912e2ec1538c71bb8836e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Fill: `#E8634A` at 90% opacity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r024", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Text: \"AI-generated slides must handle RTL text,\\nCJK line breaking, and mixed scripts correctly.\"", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 53, + "line_end": 53, + "excerpt": " - Text: \"AI-generated slides must handle RTL text,\\nCJK line breaking, and mixed scripts correctly.\"", + "excerpt_sha256": "aed6d5e1d34c47f957ca0ed73d8a508995418e93882323cc54c60b292307d22d" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Text: \"AI-generated slides must handle RTL text,\\nCJK line breaking, and mixed scripts correctly.\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r025", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Font: Liberation Sans 13pt Bold `#FFFFFF`, centered", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 54, + "line_end": 54, + "excerpt": " - Font: Liberation Sans 13pt Bold `#FFFFFF`, centered", + "excerpt_sha256": "9617340f1a4df3ed2dc6cc4a272260d9d26608f41605cf1928518b6a9692f7e9" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Font: Liberation Sans 13pt Bold `#FFFFFF`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r026", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: Corner radius: 0.3cm", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 55, + "line_end": 55, + "excerpt": " - Corner radius: 0.3cm", + "excerpt_sha256": "7ea12cd9fac64c665c5348fb0bf2eccd7eb8ceb3aa2fa5d815926239b2726594" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: Corner radius: 0.3cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-06.prompt-r027", + "scope": "slide", + "mandatory": true, + "statement": "Callout box: This callout should overlap both the Arabic and Japanese columns", + "provenance": { + "source_id": "slide-06-prompt", + "source_type": "prompt", + "line_start": 56, + "line_end": 56, + "excerpt": " - This callout should overlap both the Arabic and Japanese columns", + "excerpt_sha256": "c2f58af8ac953dceab9f2cea88fa62a503586b3d05e6856b4367877585ccec61" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Callout box: This callout should overlap both the Arabic and Japanese columns", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 6 + }, + { + "requirement_id": "slide-07.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Blank with Footer\"", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Blank with Footer\"", + "excerpt_sha256": "c075bf97eed64e2d38659376f9c3d99136cdbb4822514f5331d902fa0b26bb96" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Blank with Footer\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Three images from the asset manifest, each cropped differently:", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Three images** from the asset manifest, each cropped differently:", + "excerpt_sha256": "bc7340413542f30a42a05b92b0abf3baf2a746bb63e8b267e0b8019a6f02416a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three images from the asset manifest, each cropped differently:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Three images: `benchmark/assets/mirrored/cityscape.png`", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": " - **Image A**: `benchmark/assets/mirrored/cityscape.png`", + "excerpt_sha256": "9de8a18f653e550f4d6f42868693c5074e59bef88e6c1066d2453e32a281244f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three images: `benchmark/assets/mirrored/cityscape.png`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Size on slide: 10cm × 8cm, position (1.5cm, 2cm)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": " - Size on slide: 10cm × 8cm, position (1.5cm, 2cm)", + "excerpt_sha256": "b6f5d363e984aaf14486c5306b352003f73d38ba3e581893655424e8fb852a8b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Size on slide: 10cm × 8cm, position (1.5cm, 2cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Crop: remove top 15% and bottom 10% of original image", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": " - Crop: remove top 15% and bottom 10% of original image", + "excerpt_sha256": "d900cc09930dc29336159a1b4673d5be86415b23ed88839a95f753e5f6442ebf" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Crop: remove top 15% and bottom 10% of original image", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "No shape mask", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": " - No shape mask", + "excerpt_sha256": "d702bc2e573df5d27de7373f7915f8884a3834f7fd6ac030e090ce3a5135118c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "No shape mask", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Image A: `benchmark/assets/mirrored/cityscape.png` (same image, different crop)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " - **Image B**: `benchmark/assets/mirrored/cityscape.png` (same image, different crop)", + "excerpt_sha256": "2af3c830008c82646c3f3a434a3f5b1bd98a4299ff02377c216e54a0944f63da" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Image A: `benchmark/assets/mirrored/cityscape.png` (same image, different crop)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Size on slide: 8cm × 8cm, position (13cm, 2cm)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": " - Size on slide: 8cm × 8cm, position (13cm, 2cm)", + "excerpt_sha256": "cdd2eb51c4adc2f718c80ba8f218a2236e8c0e751e0b21ffb7fbe55cc4702862" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Size on slide: 8cm × 8cm, position (13cm, 2cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Crop: remove left 30% of original image", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " - Crop: remove left 30% of original image", + "excerpt_sha256": "ed94a139e8a61af559bb3edd647282e0e23536f01311a3419d6c51d954b15d93" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Crop: remove left 30% of original image", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Apply circle crop mask (crop to ellipse shape)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 20, + "line_end": 20, + "excerpt": " - Apply **circle crop mask** (crop to ellipse shape)", + "excerpt_sha256": "1313c13ff2c63e5ed87f335721a8f4fba91baf1ce09cd97ab9d188aa3852dc87" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Apply circle crop mask (crop to ellipse shape)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Image B: `benchmark/assets/mirrored/texture-pattern.png`", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": " - **Image C**: `benchmark/assets/mirrored/texture-pattern.png`", + "excerpt_sha256": "38fc2e3d31a2de69609ddf123c62fbe36cb753aef420ad08ec28d557a6c8af12" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Image B: `benchmark/assets/mirrored/texture-pattern.png`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Size on slide: 10cm × 8cm, position (22.5cm, 2cm)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " - Size on slide: 10cm × 8cm, position (22.5cm, 2cm)", + "excerpt_sha256": "47e17394baa5ab891d0597230fea1d3eef4b2b6bcddff4f4eda8efc5f37fca8a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Size on slide: 10cm × 8cm, position (22.5cm, 2cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Crop: remove right 25% of original image", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " - Crop: remove right 25% of original image", + "excerpt_sha256": "022ea49216bc05d13ce62dbf9c3c93b7be626fded093920bcc0bc5201cfc54bd" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Crop: remove right 25% of original image", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Apply rounded rectangle crop mask with 1cm corner radius", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " - Apply **rounded rectangle crop mask** with 1cm corner radius", + "excerpt_sha256": "607dcc7bac43e796722448349cd3d7c1aba8fd7d9a0fa474a2be04d5832a2f9d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Apply rounded rectangle crop mask with 1cm corner radius", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Caption text boxes below each image:", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": "2. **Caption text boxes** below each image:", + "excerpt_sha256": "0baa1ab56bd331e204573100f4b44d1cdaab06af3b637960a4a18ab2210fc22d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Caption text boxes below each image:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Caption text boxes: \"Full panorama crop\" / \"Circle-masked detail\" / \"Rounded corner crop\"", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " - \"Full panorama crop\" / \"Circle-masked detail\" / \"Rounded corner crop\"", + "excerpt_sha256": "8b3dacf204a5fb4acf3c4914273fae8f77411c6d27e2d781f0cc442d0a48afe7" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Caption text boxes: \"Full panorama crop\" / \"Circle-masked detail\" / \"Rounded corner crop\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Caption text boxes: Liberation Sans 12pt Italic `#F5F3EE`, centered under each image", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - Liberation Sans 12pt Italic `#F5F3EE`, centered under each image", + "excerpt_sha256": "166f384fda6a7544b691e9fea1ef0383baad3a164ca3cf53dd2be42625eb5f65" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Caption text boxes: Liberation Sans 12pt Italic `#F5F3EE`, centered under each image", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test — place a semi-transparent rectangle OVER Image B:", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": "3. **Overlapping layer test** — place a semi-transparent rectangle OVER Image B:", + "excerpt_sha256": "54fbe4730264e3be4367f4a2968ec1e05930d97d5b3078bcad88778144579c48" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test — place a semi-transparent rectangle OVER Image B:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test: Size: 6cm × 6cm", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - Size: 6cm × 6cm", + "excerpt_sha256": "d764df60ff4f7fbdcc37f46dbec1010489b42461028cc0a95b58397e52948491" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test: Size: 6cm × 6cm", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test: Position: centered on Image B", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Position: centered on Image B", + "excerpt_sha256": "d8281e091ef4a8165c3a590f9cafabaaa7311d372a3cb520e314d4d3c6627c12" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test: Position: centered on Image B", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test: Fill: `#1B2A4A` at 50% opacity", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " - Fill: `#1B2A4A` at 50% opacity", + "excerpt_sha256": "51b6c55e0e82ecaee79ae3d31bf7864f31d85f307ea957ae04200f288f28e30f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test: Fill: `#1B2A4A` at 50% opacity", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test: Text: \"PREVIEW\" in Carlito 24pt Bold `#FFFFFF`, centered", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - Text: \"PREVIEW\" in Carlito 24pt Bold `#FFFFFF`, centered", + "excerpt_sha256": "2c99160dc3ec4472e2af15ab9a7dafb2775df2c674ca6aca8b2ca19c1d33e648" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test: Text: \"PREVIEW\" in Carlito 24pt Bold `#FFFFFF`, centered", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r023", + "scope": "slide", + "mandatory": true, + "statement": "Overlapping layer test: This rectangle must be ABOVE Image B in z-order", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - This rectangle must be ABOVE Image B in z-order", + "excerpt_sha256": "de442444a95bab7472a11af71f20a643b75e0338eed103b522e94ce57b4d367f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Overlapping layer test: This rectangle must be ABOVE Image B in z-order", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-07.prompt-r024", + "scope": "slide", + "mandatory": true, + "statement": "\"Image Handling\" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm)", + "provenance": { + "source_id": "slide-07-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": "4. **Title**: \"Image Handling\" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm)", + "excerpt_sha256": "369089c9ec8c38fd58a0a43c3b86fda5d01840c6311aba026a4a15acd1cae5f9" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "\"Image Handling\" in Carlito 36pt Bold `#FFFFFF` at position (1.5cm, 0.5cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 7 + }, + { + "requirement_id": "slide-08.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Blank with Footer\"", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Blank with Footer\"", + "excerpt_sha256": "c075bf97eed64e2d38659376f9c3d99136cdbb4822514f5331d902fa0b26bb96" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Blank with Footer\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Five overlapping \"card\" shapes arranged in a cascading stack:", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Five overlapping \"card\" shapes** arranged in a cascading stack:", + "excerpt_sha256": "ae14a187067230f0dd783cb43eb6f1f7f3d367ffa3f9432f44eb69ddd144ee4a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Five overlapping \"card\" shapes arranged in a cascading stack:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm.", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": " All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm.", + "excerpt_sha256": "068c7a60b1bac3ff19537d7997d1ecdba3390b988bd18a6042551c9248492abd" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "All cards are rounded rectangles, 12cm × 8cm, corner radius 0.5cm.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes |", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes |", + "excerpt_sha256": "a4701117ddf3a114a8677fd3e1b14fb81a579e4a69a3e2a1adb45ffc0a8b32c6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 1 (bottom) | (4cm, 6cm) | `#1B2A4A` | 100% | Yes |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes |", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes |", + "excerpt_sha256": "dcaaa842f75845aa5e862870dbc87352d9048182d189dedb6e92a1bdb4d9fab3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 2 | (7cm, 5cm) | `#2AACB8` | 85% | Yes |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes |", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": " | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes |", + "excerpt_sha256": "886ddea9c59ebd05d3a26120326079fc91d686b622a8c170ea71a45414e86d75" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 3 | (10cm, 4cm) | `#E8634A` | 70% | Yes |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes |", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes |", + "excerpt_sha256": "01bc296a22e5ee2ee84bc1c7385dfa382f2a5cc0ba89d627a384a2b741a77c42" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 4 | (13cm, 3cm) | `#D4A843` | 55% | Yes |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes |", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 20, + "line_end": 20, + "excerpt": " | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes |", + "excerpt_sha256": "5e5e1d1d65216d52baf91f8d0ee350c605468298d8f5dc793526464e76704f0d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Use this exact table data row: | Card 5 (top) | (16cm, 2cm) | `#FFFFFF` | 90% | Yes |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Shadow on all cards: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm.", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": " **Shadow on all cards**: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm.", + "excerpt_sha256": "8c644a6d068cca633b8af4d48f9dd0dd7ea478ee3caee535ca18bc522ceee27d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Shadow on all cards: outer shadow, `#000000` at 30% opacity, offset 2mm down and 1mm right, blur 4mm.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Each card contains centered text:", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " Each card contains centered text:", + "excerpt_sha256": "ea92fc601c3313e207558d4a0254eae1127febb1d7139d67219835545a7cf5b1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Each card contains centered text:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Card 1: \"Layer 1\" in Liberation Sans 20pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " - Card 1: \"Layer 1\" in Liberation Sans 20pt Bold `#FFFFFF`", + "excerpt_sha256": "d71578e72eb42f48269f33a7ff62cc0749a8a3c67e1b32f13f24600cc2d3bfa3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Card 1: \"Layer 1\" in Liberation Sans 20pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Card 2: \"Layer 2\" in Liberation Sans 20pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": " - Card 2: \"Layer 2\" in Liberation Sans 20pt Bold `#FFFFFF`", + "excerpt_sha256": "676555c66205169ae0b3138ca456491daa2dcd2ce52176a967f9bbe948978c3f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Card 2: \"Layer 2\" in Liberation Sans 20pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Card 3: \"Layer 3\" in Liberation Sans 20pt Bold `#FFFFFF`", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": " - Card 3: \"Layer 3\" in Liberation Sans 20pt Bold `#FFFFFF`", + "excerpt_sha256": "bd5e26df5d225bc3bca34f843a8e68a0458fa1005cb0d98e8669d8b2d8653636" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Card 3: \"Layer 3\" in Liberation Sans 20pt Bold `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Card 4: \"Layer 4\" in Liberation Sans 20pt Bold `#1B2A4A`", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " - Card 4: \"Layer 4\" in Liberation Sans 20pt Bold `#1B2A4A`", + "excerpt_sha256": "d962e1ba029500447a043f4b16842cab714cac8fd317ba37a956750478f3f9c8" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Card 4: \"Layer 4\" in Liberation Sans 20pt Bold `#1B2A4A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Card / Position / Fill / Opacity / Shadow: Card 5: \"Layer 5\" in Liberation Sans 20pt Bold `#1B2A4A`", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - Card 5: \"Layer 5\" in Liberation Sans 20pt Bold `#1B2A4A`", + "excerpt_sha256": "adb4f7b3fc1fed352c64a492890df49cf82683e9749d6292752282be1a889c0a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Card / Position / Fill / Opacity / Shadow: Card 5: \"Layer 5\" in Liberation Sans 20pt Bold `#1B2A4A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Z-order MUST be exactly as listed: Card 1 at bottom, Card 5 on top.", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": "2. **Z-order** MUST be exactly as listed: Card 1 at bottom, Card 5 on top.", + "excerpt_sha256": "eaf0ba822f470025cab179e23ca3d2027d11e664720f947edd7f653c927dea90" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Z-order MUST be exactly as listed: Card 1 at bottom, Card 5 on top.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other.", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": "3. **Group test**: Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other.", + "excerpt_sha256": "d8fec01ec1dc3cb851d15c35f38c3337ed95f8209fdb3a5bca0a50228adfba3a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Cards 1 and 2 should be grouped together. Cards 3, 4, and 5 should be grouped together. The two groups should NOT be grouped with each other.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right).", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": "4. **Gradient fill shape**: a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right).", + "excerpt_sha256": "4cfa07456aba3564488b071bae229827b09b63fc3fbeb1ae79eb0626b64f6ce6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "a rectangle at the bottom of the slide (y=15cm, full width, 3cm tall) with a linear gradient from `#0F1923` (left) to `#2AACB8` (right).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-08.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "\"Depth & Layering\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "provenance": { + "source_id": "slide-08-prompt", + "source_type": "prompt", + "line_start": 37, + "line_end": 37, + "excerpt": "5. **Title**: \"Depth & Layering\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "excerpt_sha256": "98f75c2a3f28ec3b7a71e06cf20e0e5bc39b4ed709d8fbc55e39e015f5515b29" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "\"Depth & Layering\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 8 + }, + { + "requirement_id": "slide-09.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\"", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\"", + "excerpt_sha256": "5dfc6bde408fbce004daf9299ffaa72faaf75b10daab6fa1742a7d16fc2f684a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `API Reference`", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Title** (placeholder): `API Reference`", + "excerpt_sha256": "3532b862bf6450612d534ccfcd6fe955db6fc0333b6746cf3888bc61691e7a70" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `API Reference`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Two narrow text columns (each 14cm × 14cm, side by side):", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Two narrow text columns** (each 14cm × 14cm, side by side):", + "excerpt_sha256": "56f9c43d9497547857e38dd5efde8c5e8aed48c57b73bf3768033528b0a3379b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two narrow text columns (each 14cm × 14cm, side by side):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Left column — text box with NO auto-fit (text should clip if it overflows):", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": " **Left column** — text box with NO auto-fit (text should clip if it overflows):", + "excerpt_sha256": "7b4d85ec5a7f026a9b8d46df9ab63083f65e53674611f3a1713c530924a2438c" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Left column — text box with NO auto-fit (text should clip if it overflows):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Two narrow text columns: AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF)", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": " - AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF)", + "excerpt_sha256": "1d648846410d724035a2308ce2c83b2a5466828aff29cd430a45f02545c9517c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two narrow text columns: AutoFit: OFF (resize shape to fit text: OFF, shrink text on overflow: OFF)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Two narrow text columns: Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned):", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " - Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned):", + "excerpt_sha256": "41048a7f38c7ab9afdfd97c5dc93655901e85bd9092ada6e4357c453925593ae" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two narrow text columns: Text (Liberation Mono 11pt, `#F5F3EE`, left-aligned):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Two narrow text columns:\n GET /api/v1/submissions\n Authorization: Bearer YOUR_TOKEN_HERE\n Content-Type: application/json\n \n Query Parameters:\n model_id string required Filter by model\n tier integer optional 1, 2, or 3\n status string optional queued|grading|completed\n limit integer optional Default: 20, max: 100\n offset integer optional Default: 0\n \n Response 200:\n (\n \"submissions\": [\n (\n \"id\": \"sub_abc123\",\n \"model_id\": \"gpt-4o\",\n \"tier\": 3,\n \"status\": \"completed\",\n \"fidelity_score\": 0.847,\n \"created_at\": \"2025-01-15T10:30:00Z\"\n )\n ],\n \"total\": 142,\n \"has_more\": true\n )", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 44, + "excerpt": " ```\n GET /api/v1/submissions\n Authorization: Bearer YOUR_TOKEN_HERE\n Content-Type: application/json\n \n Query Parameters:\n model_id string required Filter by model\n tier integer optional 1, 2, or 3\n status string optional queued|grading|completed\n limit integer optional Default: 20, max: 100\n offset integer optional Default: 0\n \n Response 200:\n (\n \"submissions\": [\n (\n \"id\": \"sub_abc123\",\n \"model_id\": \"gpt-4o\",\n \"tier\": 3,\n \"status\": \"completed\",\n \"fidelity_score\": 0.847,\n \"created_at\": \"2025-01-15T10:30:00Z\"\n )\n ],\n \"total\": 142,\n \"has_more\": true\n )\n ```", + "excerpt_sha256": "9fdf5fb53acd88ea56c76b80ba14e523e7a47aa88a827475a73e309e99f29c2c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Two narrow text columns:\n GET /api/v1/submissions\n Authorization: Bearer YOUR_TOKEN_HERE\n Content-Type: application/json\n \n Query Parameters:\n model_id string required Filter by model\n tier integer optional 1, 2, or 3\n status string optional queued|grading|completed\n limit integer optional Default: 20, max: 100\n offset integer optional Default: 0\n \n Response 200:\n (\n \"submissions\": [\n (\n \"id\": \"sub_abc123\",\n \"model_id\": \"gpt-4o\",\n \"tier\": 3,\n \"status\": \"completed\",\n \"fidelity_score\": 0.847,\n \"created_at\": \"2025-01-15T10:30:00Z\"\n )\n ],\n \"total\": 142,\n \"has_more\": true\n )", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Preserve all other characters.", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 46, + "line_end": 46, + "excerpt": " Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Preserve all other characters.", + "excerpt_sha256": "57e1e9a93575d1d57fc112a8cd64eac074e0835a3a04b86c4b89f57d33930f8e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Authoring instruction; do not place this note on the slide. In the left column's slide text, replace the six JSON-structural parentheses shown in the fenced example with `{` and `}`. Preserve all other characters.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Right column — text box WITH auto-shrink enabled:", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 48, + "line_end": 48, + "excerpt": " **Right column** — text box WITH auto-shrink enabled:", + "excerpt_sha256": "c2b87a188ee395a9c0f74d555a1c0f4cf8462d5bfbe8b30c3cc0bf759208dec1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Right column — text box WITH auto-shrink enabled:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Two narrow text columns: AutoFit: Shrink text on overflow = ON", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 49, + "line_end": 49, + "excerpt": " - AutoFit: Shrink text on overflow = ON", + "excerpt_sha256": "ce34bcd76a279cf512e2f85205f417b5681954877e0383b4f54db246ee9b45d3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two narrow text columns: AutoFit: Shrink text on overflow = ON", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Two narrow text columns: Same text content as left column but with this additional block appended:", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 50, + "line_end": 50, + "excerpt": " - Same text content as left column but with this additional block appended:", + "excerpt_sha256": "cf5dd72fda6d7282e52f600310c41902450f1f0934c4db96564a46f841a1403d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two narrow text columns: Same text content as left column but with this additional block appended:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Use this fenced prompt content as directed for Two narrow text columns:\n \n Error Responses:\n 401 Unauthorized - Invalid or expired token\n 403 Forbidden - Rate limit exceeded\n 404 Not Found - Submission not found\n 422 Unprocessable - Invalid parameters\n 500 Internal Server Error - Contact support\n \n Rate Limits:\n Free tier: 10 req/min, 100 req/hour\n Pro tier: 60 req/min, 1000 req/hour\n Enterprise: Custom", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 51, + "line_end": 64, + "excerpt": " ```\n \n Error Responses:\n 401 Unauthorized - Invalid or expired token\n 403 Forbidden - Rate limit exceeded\n 404 Not Found - Submission not found\n 422 Unprocessable - Invalid parameters\n 500 Internal Server Error - Contact support\n \n Rate Limits:\n Free tier: 10 req/min, 100 req/hour\n Pro tier: 60 req/min, 1000 req/hour\n Enterprise: Custom\n ```", + "excerpt_sha256": "a63b42eb0b253561045847b5e1cf2feff418d3e6162b4a8ef2cd42ce91fd3408" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use this fenced prompt content as directed for Two narrow text columns:\n \n Error Responses:\n 401 Unauthorized - Invalid or expired token\n 403 Forbidden - Rate limit exceeded\n 404 Not Found - Submission not found\n 422 Unprocessable - Invalid parameters\n 500 Internal Server Error - Contact support\n \n Rate Limits:\n Free tier: 10 req/min, 100 req/hour\n Pro tier: 60 req/min, 1000 req/hour\n Enterprise: Custom", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Column labels above each:", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 66, + "line_end": 66, + "excerpt": "3. **Column labels** above each:", + "excerpt_sha256": "f825bd06243ead7a7b6a3979425604475ae6d2604d3f0da787feb070d57b345e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column labels above each:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Column labels: \"Fixed Size (clips)\" over left column — Liberation Sans 11pt Bold `#E8634A`", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 67, + "line_end": 67, + "excerpt": " - \"Fixed Size (clips)\" over left column — Liberation Sans 11pt Bold `#E8634A`", + "excerpt_sha256": "e9881d649246243860862c7ad675d6bc83157cce23f82ab8fd795e003b35d172" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column labels: \"Fixed Size (clips)\" over left column — Liberation Sans 11pt Bold `#E8634A`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Column labels: \"Auto-Shrink (fits)\" over right column — Liberation Sans 11pt Bold `#2AACB8`", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 68, + "line_end": 68, + "excerpt": " - \"Auto-Shrink (fits)\" over right column — Liberation Sans 11pt Bold `#2AACB8`", + "excerpt_sha256": "47b14b5be43a9a41847be9c10054aa86d7a839b73b5285410ca1ae435c2e3d45" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column labels: \"Auto-Shrink (fits)\" over right column — Liberation Sans 11pt Bold `#2AACB8`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-09.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "exactly 1.15× throughout both columns.", + "provenance": { + "source_id": "slide-09-prompt", + "source_type": "prompt", + "line_start": 70, + "line_end": 70, + "excerpt": "4. **Line spacing**: exactly 1.15× throughout both columns.", + "excerpt_sha256": "43aff691852d82d52c922282288c890a91ba1d1992e7c2016e3fae856810ca3d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "exactly 1.15× throughout both columns.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 9 + }, + { + "requirement_id": "slide-10.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Blank with Footer\"", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Blank with Footer\"", + "excerpt_sha256": "c075bf97eed64e2d38659376f9c3d99136cdbb4822514f5331d902fa0b26bb96" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Blank with Footer\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Architecture diagram using ONLY built-in shapes and connectors:", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Architecture diagram** using ONLY built-in shapes and connectors:", + "excerpt_sha256": "82da7e172b884fe25696c93e5743e95c349e9f75c38f4f7360f42f4711540bc8" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Architecture diagram using ONLY built-in shapes and connectors:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Boxes (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm):", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": " **Boxes** (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm):", + "excerpt_sha256": "1a4ae3c73040f02961203883c7d40329369a4c4cbe681001eb12b1ab66d2eaa1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Boxes (all rounded rectangles, 5cm × 3cm, corner radius 0.3cm):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | Client | \"Client App\" | (2cm, 3cm) | `#2AACB8` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " | Client | \"Client App\" | (2cm, 3cm) | `#2AACB8` |", + "excerpt_sha256": "73357f0ff162d6206debeb7ac23a3905a7ac6acd90cc8c6b4136e68ff4bcf2d7" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | Client | \"Client App\" | (2cm, 3cm) | `#2AACB8` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | API Gateway | \"API Gateway\" | (14cm, 3cm) | `#1B2A4A` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " | API Gateway | \"API Gateway\" | (14cm, 3cm) | `#1B2A4A` |", + "excerpt_sha256": "f5ec056f2637c45609a2941b39eedbc67c126598046f5b60e1eea6000c734801" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | API Gateway | \"API Gateway\" | (14cm, 3cm) | `#1B2A4A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | Auth | \"Auth Service\" | (8cm, 9cm) | `#E8634A` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 18, + "line_end": 18, + "excerpt": " | Auth | \"Auth Service\" | (8cm, 9cm) | `#E8634A` |", + "excerpt_sha256": "af411f59d0082106c7330fe3609ee30f7c5d8f21ea4e517d5805b1e052546d90" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | Auth | \"Auth Service\" | (8cm, 9cm) | `#E8634A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | Grader | \"Grader\" | (20cm, 9cm) | `#E8634A` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " | Grader | \"Grader\" | (20cm, 9cm) | `#E8634A` |", + "excerpt_sha256": "a3a6e8dee7c57ecd4ef8bd1945bcbdbfc516635a54ec62b8d186a8121914623c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | Grader | \"Grader\" | (20cm, 9cm) | `#E8634A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | Queue | \"Job Queue\" | (14cm, 9cm) | `#D4A843` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 20, + "line_end": 20, + "excerpt": " | Queue | \"Job Queue\" | (14cm, 9cm) | `#D4A843` |", + "excerpt_sha256": "d78ba7b6643969d972d60f27617a3ea8f18f9edd8207461d982c227a8eb6584d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | Queue | \"Job Queue\" | (14cm, 9cm) | `#D4A843` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | Storage | \"Object Store\" | (14cm, 15cm) | `#1B2A4A` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 21, + "line_end": 21, + "excerpt": " | Storage | \"Object Store\" | (14cm, 15cm) | `#1B2A4A` |", + "excerpt_sha256": "149ba2afda4dc566934f5fb2d3f828b06d08bd566961fe70f1149b530fe3184d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | Storage | \"Object Store\" | (14cm, 15cm) | `#1B2A4A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | DB | \"PostgreSQL\" | (6cm, 15cm) | `#1B2A4A` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": " | DB | \"PostgreSQL\" | (6cm, 15cm) | `#1B2A4A` |", + "excerpt_sha256": "a1ed62170d1f2ef5035560f5f47053e48ecae0772dc4ebd77f2941e882fbb76c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | DB | \"PostgreSQL\" | (6cm, 15cm) | `#1B2A4A` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Box / Label / Position / Fill: Use this exact table data row: | LB | \"Leaderboard\" | (22cm, 15cm) | `#2AACB8` |", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " | LB | \"Leaderboard\" | (22cm, 15cm) | `#2AACB8` |", + "excerpt_sha256": "5878b9d1e00aba4e45d8a30288f807f550f44564a0b16cdef4deddcbf71fbbd6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Box / Label / Position / Fill: Use this exact table data row: | LB | \"Leaderboard\" | (22cm, 15cm) | `#2AACB8` |", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "No pair of architecture boxes overlaps.", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 25, + "line_end": 25, + "excerpt": " No pair of architecture boxes overlaps.", + "excerpt_sha256": "49cb5c32205b99c81cfa4256c08f999c0c6b7a31414c4a4563d0203ca6b43216" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "No pair of architecture boxes overlaps.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered.", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": " All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered.", + "excerpt_sha256": "5fdd216e638f008cb108e1a594dc3bdec0c75b950322009c90de044ba73b9d20" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "All box text: Liberation Sans 12pt Bold `#FFFFFF`, centered.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Connectors — use native connectors (Insert → Connector in LibreOffice), NOT plain lines:", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": "2. **Connectors** — use native connectors (Insert → Connector in LibreOffice), NOT plain lines:", + "excerpt_sha256": "bd8877f591295343f9c39517bca13e36391647a5d1755f94f399a5a84bf624b2" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors — use native connectors (Insert → Connector in LibreOffice), NOT plain lines:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: Client → API Gateway (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": " - Client → API Gateway (straight connector, arrow at end)", + "excerpt_sha256": "e714fc1520ab16529b593d1c912d29e11629db5980d9a415feb7efba563892e1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: Client → API Gateway (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: API Gateway → Auth (elbow connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - API Gateway → Auth (elbow connector, arrow at end)", + "excerpt_sha256": "429d18253e871c4303bbafab9b146c909b7d8633c38a2a761759468b1c28968e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: API Gateway → Auth (elbow connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: API Gateway → Queue (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - API Gateway → Queue (straight connector, arrow at end)", + "excerpt_sha256": "9da2fd45218b6392f6c0b017b19c1b0333d0e33d686816134c70514d3515ba76" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: API Gateway → Queue (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: Queue → Grader (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Queue → Grader (straight connector, arrow at end)", + "excerpt_sha256": "f151002a0158d3b98d1d43a8403ba1d06b956f2b4f6d46bb62e19b459234cd49" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: Queue → Grader (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r019", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: Grader → Storage (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 34, + "line_end": 34, + "excerpt": " - Grader → Storage (straight connector, arrow at end)", + "excerpt_sha256": "99a7b786c12804de82744ee79d202fb31f94ba9fd5226c6fd0072146c7d8d68b" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: Grader → Storage (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r020", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: Storage → DB (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 35, + "line_end": 35, + "excerpt": " - Storage → DB (straight connector, arrow at end)", + "excerpt_sha256": "a5536cb14836be10cd0ce1d992fd778f0812cffea4c581427021ed3e5846ce4c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: Storage → DB (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r021", + "scope": "slide", + "mandatory": true, + "statement": "Connectors: Storage → LB (straight connector, arrow at end)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 36, + "line_end": 36, + "excerpt": " - Storage → LB (straight connector, arrow at end)", + "excerpt_sha256": "ef88e60b2d436bed958c451f296454d56dac281a5479fb63aed31b92bcfbca0a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Connectors: Storage → LB (straight connector, arrow at end)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r022", + "scope": "slide", + "mandatory": true, + "statement": "All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end.", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 38, + "line_end": 38, + "excerpt": " All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end.", + "excerpt_sha256": "157cd03e6679ce68bd2d00ab426031ab45ceeb5c498d39ad9e744058a9eb9e00" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "All connectors: 1.5pt, `#F5F3EE`, with arrowhead at destination end.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r023", + "scope": "slide", + "mandatory": true, + "statement": "Labels on connectors — small text boxes positioned near each connector:", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 40, + "line_end": 40, + "excerpt": "3. **Labels on connectors** — small text boxes positioned near each connector:", + "excerpt_sha256": "ec33328498debcd870e56ab938dca825acecd9e455e2be6e04cc4b774ca7d915" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Labels on connectors — small text boxes positioned near each connector:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r024", + "scope": "slide", + "mandatory": true, + "statement": "Labels on connectors: Client→Gateway: \"HTTPS\" (Liberation Sans 10pt `#FFFFFF`)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 41, + "line_end": 41, + "excerpt": " - Client→Gateway: \"HTTPS\" (Liberation Sans 10pt `#FFFFFF`)", + "excerpt_sha256": "f64a5d275078b346049ab0f1df61b9f20931d6cef055a3caf0cdce20ce5226db" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Labels on connectors: Client→Gateway: \"HTTPS\" (Liberation Sans 10pt `#FFFFFF`)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r025", + "scope": "slide", + "mandatory": true, + "statement": "Labels on connectors: Gateway→Auth: \"JWT verify\" (Liberation Sans 10pt `#FFFFFF`)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 42, + "line_end": 42, + "excerpt": " - Gateway→Auth: \"JWT verify\" (Liberation Sans 10pt `#FFFFFF`)", + "excerpt_sha256": "4f9f071a6dc1c26fb25b1e84621045ae58fb90456ab06c30e899f3bd6083057e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Labels on connectors: Gateway→Auth: \"JWT verify\" (Liberation Sans 10pt `#FFFFFF`)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r026", + "scope": "slide", + "mandatory": true, + "statement": "Labels on connectors: Gateway→Queue: \"Enqueue\" (Liberation Sans 10pt `#FFFFFF`)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 43, + "line_end": 43, + "excerpt": " - Gateway→Queue: \"Enqueue\" (Liberation Sans 10pt `#FFFFFF`)", + "excerpt_sha256": "cc8acb08aedfd6859eba91e0722b2cb5a5fbfe21765bb684ce6dd0c128b8307a" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Labels on connectors: Gateway→Queue: \"Enqueue\" (Liberation Sans 10pt `#FFFFFF`)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r027", + "scope": "slide", + "mandatory": true, + "statement": "Nested grouping: Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text \"Processing Layer\" above)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 46, + "line_end": 46, + "excerpt": " - Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text \"Processing Layer\" above)", + "excerpt_sha256": "d0398937bf1a7b6d5a10c5dc318a9228b4803c1b6b252b1f6c54fc69a35ebb8e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Nested grouping: Group 1: Auth + Queue + Grader boxes (label this group with a thin dashed border, 0.5pt `#FFFFFF` at 30%, and text \"Processing Layer\" above)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r028", + "scope": "slide", + "mandatory": true, + "statement": "Nested grouping: Group 2: Storage + DB + LB boxes (label with \"Persistence Layer\")", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 47, + "line_end": 47, + "excerpt": " - Group 2: Storage + DB + LB boxes (label with \"Persistence Layer\")", + "excerpt_sha256": "ec578cd81364fb04d8c7728249824c59e459d5b0f96ea71c861ae804c10c75c5" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Nested grouping: Group 2: Storage + DB + LB boxes (label with \"Persistence Layer\")", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r029", + "scope": "slide", + "mandatory": true, + "statement": "Nested grouping: Group 3: Group 1 + Group 2 (the \"Backend\" super-group)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 48, + "line_end": 48, + "excerpt": " - Group 3: Group 1 + Group 2 (the \"Backend\" super-group)", + "excerpt_sha256": "73cb7052551611dd7b5e12a17886d259011c0a0ef827629867d4baef8237f20c" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Nested grouping: Group 3: Group 1 + Group 2 (the \"Backend\" super-group)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-10.prompt-r030", + "scope": "slide", + "mandatory": true, + "statement": "\"System Architecture\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "provenance": { + "source_id": "slide-10-prompt", + "source_type": "prompt", + "line_start": 50, + "line_end": 50, + "excerpt": "5. **Title**: \"System Architecture\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "excerpt_sha256": "403898104fb7c66bdcd3305ce6fe020805701a8e16f8ca5bd8a4889d47fb5e93" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "\"System Architecture\" — Carlito 36pt Bold `#FFFFFF`, position (1.5cm, 0.5cm)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 10 + }, + { + "requirement_id": "slide-11.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\"", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\"", + "excerpt_sha256": "5dfc6bde408fbce004daf9299ffaa72faaf75b10daab6fa1742a7d16fc2f684a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `Brand Colors`", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Title** (placeholder): `Brand Colors`", + "excerpt_sha256": "49322521700f6417897df1b598a36c42af6689547e758cb6fc1d939c8112e0cb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `Brand Colors`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row.", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Six color swatches in two rows of three** — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row.", + "excerpt_sha256": "a46302371be97818daed94b0f92bb62036bf71326f1944b6c9b4eb4eb9abed0c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three — each is a 4cm × 4cm rounded rectangle. Swatches 1–3 are the top row; Swatches 4–6 are the bottom row.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Top row — inherited from theme/master (these must use theme color references, NOT hardcoded hex):", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": " **Top row — inherited from theme/master** (these must use theme color references, NOT hardcoded hex):", + "excerpt_sha256": "e25ef9dd556c809f1642492d2bc5774941021b402789c82a99c7e49e75fbb706" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Top row — inherited from theme/master (these must use theme color references, NOT hardcoded hex):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 1: Theme Primary color", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": " - Swatch 1: Theme Primary color", + "excerpt_sha256": "6091ab5342a6ec39827f8a8b37ab0489c7dd74a8d0cafe28bfe3f5606794f239" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 1: Theme Primary color", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 2: Theme Secondary color", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " - Swatch 2: Theme Secondary color", + "excerpt_sha256": "0a0b49273937a5fe213f537e193d344ab9e7548f2f6d2075241791a8ff3aa08e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 2: Theme Secondary color", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 3: Theme Accent 1 color", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " - Swatch 3: Theme Accent 1 color", + "excerpt_sha256": "a48927ec3a5e20fce26dff150fc3e826bdc661cc41b6692e747d81eef0b9d621" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 3: Theme Accent 1 color", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Below each: text with the role name (\"Primary\", \"Secondary\", \"Accent 1\") in Liberation Sans 12pt `#F5F3EE`", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 19, + "line_end": 19, + "excerpt": " Below each: text with the role name (\"Primary\", \"Secondary\", \"Accent 1\") in Liberation Sans 12pt `#F5F3EE`", + "excerpt_sha256": "e647e1b708d7aecd7116fde5aa2abe09914c66e1d9aac865f5d93c5d2531b1b6" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Below each: text with the role name (\"Primary\", \"Secondary\", \"Accent 1\") in Liberation Sans 12pt `#F5F3EE`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Bottom row — locally overridden (these must use explicit RGB hex, NOT theme references):", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 21, + "line_end": 21, + "excerpt": " **Bottom row — locally overridden** (these must use explicit RGB hex, NOT theme references):", + "excerpt_sha256": "58cac08dd01442f75c696cda4c0bef8ac81aab053a1d44e8d7ec781eb394f126" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Bottom row — locally overridden (these must use explicit RGB hex, NOT theme references):", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 4: `#FF6B35` (explicit override — different from theme)", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 22, + "line_end": 22, + "excerpt": " - Swatch 4: `#FF6B35` (explicit override — different from theme)", + "excerpt_sha256": "0de16eb1c31bdad962f34c1c3e8062006ef8d882fd02462a213d2a3210e5cc5c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 4: `#FF6B35` (explicit override — different from theme)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 5: `#7B2D8E` (explicit override)", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " - Swatch 5: `#7B2D8E` (explicit override)", + "excerpt_sha256": "d541720e61b5bf1f96bcc1e422700563a86f958029f03fc9efcefb3656c87519" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 5: `#7B2D8E` (explicit override)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Six color swatches in two rows of three: Swatch 6: `#3D9970` (explicit override)", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " - Swatch 6: `#3D9970` (explicit override)", + "excerpt_sha256": "ae7d83e487bcd0a373b9dff79f032d02a152904e5f5de6159884e416a253687f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Six color swatches in two rows of three: Swatch 6: `#3D9970` (explicit override)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Below each: text \"Override\" in Liberation Sans 12pt, same explicit color as the swatch", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": " Below each: text \"Override\" in Liberation Sans 12pt, same explicit color as the swatch", + "excerpt_sha256": "9fb2dfad73cb742b41e0320dfa9bff6598a19a0a49fbadb7adb9e49b1fb759a0" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Below each: text \"Override\" in Liberation Sans 12pt, same explicit color as the swatch", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML.", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": "3. **The critical test**: if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML.", + "excerpt_sha256": "6464eb3105f2d609a5a84669e78f113d1fc95cd0a2b4fcbbd244904e5cf5766f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "if someone changes the theme colors in the master, the top row should change with the theme but the bottom row should stay fixed. This is what the grader checks — theme reference vs. local override in the OOXML.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory text box at bottom:", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": "4. **Explanatory text box** at bottom:", + "excerpt_sha256": "035fa6cbb63bd184156c9333fa99d36ad855eb31ca04abffa57bb10046f0b091" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory text box at bottom:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r016", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory text box: \"Top row uses theme color references. Bottom row uses explicit RGB values.\"", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 31, + "line_end": 31, + "excerpt": " - \"Top row uses theme color references. Bottom row uses explicit RGB values.\"", + "excerpt_sha256": "052fe4870a3180141362c516867c2c82ae38dc63a7d22417eb24558ffd926ad1" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory text box: \"Top row uses theme color references. Bottom row uses explicit RGB values.\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r017", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory text box: \"Changing the theme will update the top row but not the bottom row.\"", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": " - \"Changing the theme will update the top row but not the bottom row.\"", + "excerpt_sha256": "1ace4508995120d1a6c486cd187f3ecdb7b7a874fee8da11b3b51f86f6f76f09" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory text box: \"Changing the theme will update the top row but not the bottom row.\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-11.prompt-r018", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory text box: Liberation Sans 13pt `#F5F3EE`", + "provenance": { + "source_id": "slide-11-prompt", + "source_type": "prompt", + "line_start": 33, + "line_end": 33, + "excerpt": " - Liberation Sans 13pt `#F5F3EE`", + "excerpt_sha256": "1195fbcad6523813ed3f3a674be5ed898783dd778d4769187d53c712ace418bb" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory text box: Liberation Sans 13pt `#F5F3EE`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 11 + }, + { + "requirement_id": "slide-12.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Layout: \"Content Slide\"", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "**Layout:** \"Content Slide\"", + "excerpt_sha256": "5dfc6bde408fbce004daf9299ffaa72faaf75b10daab6fa1742a7d16fc2f684a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Layout: \"Content Slide\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Title (placeholder): `Document Fields`", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "1. **Title** (placeholder): `Document Fields`", + "excerpt_sha256": "f5f1864de1e185afaaf48e9bb01983cfd0fdb027f0ec98c0b22fc10d4dd6c28c" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Title (placeholder): `Document Fields`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Three field demonstrations — each in its own text box:", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "2. **Three field demonstrations** — each in its own text box:", + "excerpt_sha256": "7258b53c73738980a0101bfa1e6ee8a8a28678026a0b8482135daccc4afbec59" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Three field demonstrations — each in its own text box:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Field 1 — Slide Number: Text box: \"Current slide: \" followed by an inserted slide number field (LibreOffice: Insert → Field → Page Number)", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": " - Text box: \"Current slide: \" followed by an **inserted slide number field** (LibreOffice: Insert → Field → Page Number)", + "excerpt_sha256": "0be0f7252bb7f6480ffaa06d6e2036f8545e88dc8fda3b528b6202645a0ac01e" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 1 — Slide Number: Text box: \"Current slide: \" followed by an inserted slide number field (LibreOffice: Insert → Field → Page Number)", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Field 1 — Slide Number: Do NOT type the number manually. It MUST be a live field.", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 16, + "line_end": 16, + "excerpt": " - Do NOT type the number manually. It MUST be a live field.", + "excerpt_sha256": "c8b2272d10c0a8e674ea2ed743d54d4bf5f690977354bd46068d1f5a2a0e62dd" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 1 — Slide Number: Do NOT type the number manually. It MUST be a live field.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Field 1 — Slide Number: Liberation Sans 18pt `#FFFFFF`", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 17, + "line_end": 17, + "excerpt": " - Liberation Sans 18pt `#FFFFFF`", + "excerpt_sha256": "9dde812786c68108004ea86f47d7da75c47677818020da76ceec5e7bcf77bb8f" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 1 — Slide Number: Liberation Sans 18pt `#FFFFFF`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Field 2 — Date/Time: `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed exactly as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`.", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 20, + "line_end": 20, + "excerpt": " - `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed exactly as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`.", + "excerpt_sha256": "5f49519d2b8ffb238d1e6cd07a9c141469fe7a8c0a6725bbc919edfa9742f180" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 2 — Date/Time: `Generated: ` followed by a fixed native date/time field with value `2025-01-15T10:30:00Z`, displayed exactly as `2025-01-15 10:30 UTC`; Liberation Sans 18pt `#FFFFFF`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r008", + "scope": "slide", + "mandatory": true, + "statement": "Field 3 — Footer: The slide footer (from View → Header and Footer) should contain: \"AcidSlide Benchmark v1\"", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 23, + "line_end": 23, + "excerpt": " - The slide footer (from View → Header and Footer) should contain: \"AcidSlide Benchmark v1\"", + "excerpt_sha256": "ed20a11e823f1f4592006485bf1626b3eb5ee803e1c3b3902b44a3dac5809fe9" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 3 — Footer: The slide footer (from View → Header and Footer) should contain: \"AcidSlide Benchmark v1\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r009", + "scope": "slide", + "mandatory": true, + "statement": "Field 3 — Footer: This must be enabled via the master's footer placeholder", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 24, + "line_end": 24, + "excerpt": " - This must be enabled via the master's footer placeholder", + "excerpt_sha256": "57c9ea8748d615d42ad3647855e784a8291cc0889f61966734cd8b004f24484a" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Field 3 — Footer: This must be enabled via the master's footer placeholder", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r010", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory labels next to each:", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 26, + "line_end": 26, + "excerpt": "3. **Explanatory labels** next to each:", + "excerpt_sha256": "01253f04c84a4f9a956b37a5671de05e9486a2e8f3757b38f0d026120d13ac80" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory labels next to each:", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r011", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory labels: \"← Live slide number field (not static text)\"", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 27, + "line_end": 27, + "excerpt": " - \"← Live slide number field (not static text)\"", + "excerpt_sha256": "607a3c68356658922fb182eb0095135c5adde7cd249aa0e716a07ce5aec7266c" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory labels: \"← Live slide number field (not static text)\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r012", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory labels: \"← Fixed date/time field\"", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 28, + "line_end": 28, + "excerpt": " - \"← Fixed date/time field\"", + "excerpt_sha256": "48a23775ce960bac6e4a41d01774142893350fb7895e224023ac64e213bae9aa" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory labels: \"← Fixed date/time field\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r013", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory labels: \"← Footer from master placeholder\"", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 29, + "line_end": 29, + "excerpt": " - \"← Footer from master placeholder\"", + "excerpt_sha256": "c9b56027e6abc5bf843b370b7951c62000d754ba6e7ecfa5d22380997b0e9044" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory labels: \"← Footer from master placeholder\"", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r014", + "scope": "slide", + "mandatory": true, + "statement": "Explanatory labels: Liberation Sans 12pt Italic `#2AACB8`", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 30, + "line_end": 30, + "excerpt": " - Liberation Sans 12pt Italic `#2AACB8`", + "excerpt_sha256": "3582b18a6cf4e19eac8b689cb0c54423cd075ac43181dbfc0470d330e398a69d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Explanatory labels: Liberation Sans 12pt Italic `#2AACB8`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-12.prompt-r015", + "scope": "slide", + "mandatory": true, + "statement": "A static text comparison — a text box that says \"Slide 12\" in the same font/size as Field 1, to highlight the difference between static text and a live field.", + "provenance": { + "source_id": "slide-12-prompt", + "source_type": "prompt", + "line_start": 32, + "line_end": 32, + "excerpt": "4. **A static text comparison** — a text box that says \"Slide 12\" in the same font/size as Field 1, to highlight the difference between static text and a live field.", + "excerpt_sha256": "9867451395716ed6d642d7da81d0c0c74f5da8c9e75cb9b3d467063f567f474c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "A static text comparison — a text box that says \"Slide 12\" in the same font/size as Field 1, to highlight the difference between static text and a live field.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 12 + }, + { + "requirement_id": "slide-13.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations.", + "excerpt_sha256": "233c9c75b609d61b54da34dbc54464cb9b4e4313363b8e291b1887f9347bca5d" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Combines: native chart (pie chart, 6 segments), native table (4×3), one approved image, Arabic text annotation, repeated layout elements, dense callout annotations.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm).", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Blank with Footer** layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm).", + "excerpt_sha256": "1111345abeca591160e4440f7183b90a631eb345c997b37990d3a74aae8470ba" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Add one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Use six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Add one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Use six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend.", + "excerpt_sha256": "0503337b77893d15714279e5203c48df67cef92ce62fd3e0bf59e692da3ea563" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Use six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Add one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Add one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`.", + "excerpt_sha256": "d2a99be011adbd0fd1d81be50a02948fb4233de45e539c6d6ca6320faa4bcc1f" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Insert `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Use only asset ID `cityscape` from the manifest.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Insert `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Use only asset ID `cityscape` from the manifest.", + "excerpt_sha256": "ab820af32a0aff65d1d8e0bb28becefe8d24e9155098184cb4ebae721533a457" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Insert `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Use only asset ID `cityscape` from the manifest.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Add the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": "- Add the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction.", + "excerpt_sha256": "4b7f0a0ae1b3c153286c3789de94301a0e0dcf7ea570d0a519e377f0b3c9adfb" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-13.prompt-r007", + "scope": "slide", + "mandatory": true, + "statement": "Add three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible.", + "provenance": { + "source_id": "slide-13-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": "- Add three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible.", + "excerpt_sha256": "0daa740941a6263f850b06fa96fd6ebd9dad4a2e68f6df5f53a46773fffcbdcf" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 13 + }, + { + "requirement_id": "slide-14.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., \"The الذكاء الاصطناعي revolution\"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned.", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., \"The الذكاء الاصطناعي revolution\"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned.", + "excerpt_sha256": "fb89afa54847d70ecfb428f15e20e55f2ac0d378fc812a05c0b3b6323d039d73" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Two-column layout with heavy Arabic text on left (5+ paragraphs with mixed Arabic/English), English summary on right. Bidirectional text within single paragraphs (e.g., \"The الذكاء الاصطناعي revolution\"). Mirrored alignment: Arabic column is right-aligned, English column is left-aligned.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-14.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Two-Column layout with title `RTL Systems Review`.", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Two-Column** layout with title `RTL Systems Review`.", + "excerpt_sha256": "822d4a35170aa88d9fc9003cd33baa6f98199abec2592ff8c7780dfed8ab7c8b" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Two-Column layout with title `RTL Systems Review`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-14.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`.", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`.", + "excerpt_sha256": "8cbb012f07f39c49a5d8cc10393050ffd78593275c1a39445c73faefab022ea9" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-14.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.`", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.`", + "excerpt_sha256": "f0defa03b28072a7ff591559fa7b742458c416c4bff4b3a2c78af01a206b20f7" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-14.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them.", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them.", + "excerpt_sha256": "2fa0228291762e155c047278f02bed9dbc2ea7bb190d9665387ab79844fe09ef" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-14.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines.", + "provenance": { + "source_id": "slide-14-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": "- Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines.", + "excerpt_sha256": "51bb314c3e0b9cf920a4659792dca6f2dfef04efde492b7012d97036bf857f5d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 14 + }, + { + "requirement_id": "slide-15.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Tests exact anchor points for rotated elements.", + "provenance": { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Tests exact anchor points for rotated elements.", + "excerpt_sha256": "1d0a74d330d8e3c3147a549551e49d08eded3603cde3b406333656bf15bed7c3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Multiple text boxes at different rotation angles: 0°, 45°, 90°, 135°, 270°. Supporting shapes aligned to the rotated text. Tests exact anchor points for rotated elements.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 15 + }, + { + "requirement_id": "slide-15.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout with title `Rotation Atlas`.", + "provenance": { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Blank with Footer** layout with title `Rotation Atlas`.", + "excerpt_sha256": "ea187c502cbbd94c23c0e18711f4d27fb31eb03944333c12d97ef8a6aa4243bf" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout with title `Rotation Atlas`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 15 + }, + { + "requirement_id": "slide-15.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Create five text boxes labeled exactly `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`.", + "provenance": { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Create five text boxes labeled exactly `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`.", + "excerpt_sha256": "22999589e17e85dd1735799fcb66ee4747a29c1d5ccdb3c701b7c7762a52fe34" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Create five text boxes labeled exactly `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 15 + }, + { + "requirement_id": "slide-15.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Apply rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation.", + "provenance": { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Apply rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation.", + "excerpt_sha256": "8c351f043e728e61a5b6e1ca6f2b9e2c7bdea01f1d3c95bc91c5acfc0b7ba45c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Apply rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 15 + }, + { + "requirement_id": "slide-15.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Keep text editable and store rotations in native OOXML transforms.", + "provenance": { + "source_id": "slide-15-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Keep text editable and store rotations in native OOXML transforms.", + "excerpt_sha256": "bfa0c1dcf6d4eec2c08549577121643bd69e0a5f5e13f867a28c57dceb246291" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Keep text editable and store rotations in native OOXML transforms.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 15 + }, + { + "requirement_id": "slide-16.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors.", + "provenance": { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors.", + "excerpt_sha256": "846b1614e19e85f7cbde947569edc0d970e519b719e26da710ed4611d3f9e3f2" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Objects deliberately extending beyond the slide canvas edges — a large circle at (-3cm, -2cm) partly visible, a rectangle extending 5cm past the right edge. These are intentional design choices, not errors.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 16 + }, + { + "requirement_id": "slide-16.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout with title `Beyond the Frame`.", + "provenance": { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Blank with Footer** layout with title `Beyond the Frame`.", + "excerpt_sha256": "eed4896f58c70f9f8751eeabe96fc3b39c4fc821bc89ebdb837e127885f76b56" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout with title `Beyond the Frame`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 16 + }, + { + "requirement_id": "slide-16.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Place a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm).", + "provenance": { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Place a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm).", + "excerpt_sha256": "5b12cc6fdc332d494db00d9dbdec7c5d4caae72b7da62536a8e37e325595335d" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Place a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 16 + }, + { + "requirement_id": "slide-16.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Add on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.`", + "provenance": { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Add on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.`", + "excerpt_sha256": "a720b6de38bf66147c2d83a7f6d6176b17ff657c94faf380bb0a9f52968cb6c2" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 16 + }, + { + "requirement_id": "slide-16.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Preserve negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas.", + "provenance": { + "source_id": "slide-16-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Preserve negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas.", + "excerpt_sha256": "cfb3c659a763641e19e58321e4f21735e4df9de9891e68424cf794877f133efd" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Preserve negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 16 + }, + { + "requirement_id": "slide-17.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "3 levels of nested groups. Inner groups contain exactly 3 shapes each. Middle groups contain exactly 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level.", + "provenance": { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "3 levels of nested groups. Inner groups contain exactly 3 shapes each. Middle groups contain exactly 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level.", + "excerpt_sha256": "feda5a45f0692fe76d3cc50d8360e1c1ec7c821e6074df20a5d421ee114f82a3" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "3 levels of nested groups. Inner groups contain exactly 3 shapes each. Middle groups contain exactly 2 inner groups. Outer group wraps everything. Z-order must be exact within each nesting level.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 17 + }, + { + "requirement_id": "slide-17.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout with title `Nested Systems`.", + "provenance": { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Blank with Footer** layout with title `Nested Systems`.", + "excerpt_sha256": "7763aa51c5339f008ebdcc14d8232106ea0c9186c439c7fdac7f928fa78b2be8" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout with title `Nested Systems`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 17 + }, + { + "requirement_id": "slide-17.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Build one outer group containing three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total).", + "provenance": { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Build one outer group containing three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total).", + "excerpt_sha256": "eccf67fc2187317245a8c6dd36f3cf22044075a2cabac4de66f4a5c1ac7d4ad5" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Build one outer group containing three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 17 + }, + { + "requirement_id": "slide-17.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Use native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`.", + "provenance": { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Use native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`.", + "excerpt_sha256": "9088578163b0705d3801651fe6eb5796c0a19ad92a3075529c3aeff75a2a7e2e" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 17 + }, + { + "requirement_id": "slide-17.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Within every inner group, z-order is circle below rounded rectangle below label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm.", + "provenance": { + "source_id": "slide-17-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Within every inner group, z-order is circle below rounded rectangle below label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm.", + "excerpt_sha256": "f4e0405d122f3cc8a6450bcfac2a1d04ae34bb13d1824a2396a6107928ab03df" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Within every inner group, z-order is circle below rounded rectangle below label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 17 + }, + { + "requirement_id": "slide-18.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column.", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column.", + "excerpt_sha256": "d537c13e76fc3d0c644a74b001b32e94bd65c0c94f88dcb1d41f8614706cd262" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "3-column magazine-style layout with mixed English/Japanese text. Each column has a header image (from assets), body text, and a pull quote. Pattern fill on the background of one column.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-18.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout with title `Three Cities / 三つの都市`.", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Blank with Footer** layout with title `Three Cities / 三つの都市`.", + "excerpt_sha256": "93d0b7840615026b80133137f6fbf5294836cbbce78d143c0830061eabbc8fa8" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout with title `Three Cities / 三つの都市`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-18.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote.", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote.", + "excerpt_sha256": "40467f10cf56ca1e41dad9b55fb98bac84556dbfe5e9c88f3a513f9024032e02" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-18.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media.", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media.", + "excerpt_sha256": "45e22442e79372da7e8a33c8fff636e3fde99953d3e8341191042df31620391f" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-18.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。`", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。`", + "excerpt_sha256": "204501620aef9f35807cc995e95417d6b39495d8eb92c950b0167bd3d865ce70" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。`", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-18.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Apply the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Use 0.9cm gutters consistently.", + "provenance": { + "source_id": "slide-18-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": "- Apply the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Use 0.9cm gutters consistently.", + "excerpt_sha256": "b1e4f254adebf966ac5cb8dd91e9f71c0c9bf0c9ea889d4988ab7ca0abd8e58c" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Apply the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Use 0.9cm gutters consistently.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 18 + }, + { + "requirement_id": "slide-19.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights exactly. Tests deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs).", + "provenance": { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights exactly. Tests deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs).", + "excerpt_sha256": "357f0ac1e673d89af5129dbb5a8fcc778f2929e1ec7307694c083a0217c6342e" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Visually identical to the design system — every element must match the master's font sizes, colors, spacing, and line weights exactly. Tests deck-wide consistency. Internal hyperlinks to Slides 1 and 5 (not external URLs).", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 19 + }, + { + "requirement_id": "slide-19.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Content Slide layout with title `Design System Audit`.", + "provenance": { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "line_start": 9, + "line_end": 9, + "excerpt": "- Use the **Content Slide** layout with title `Design System Audit`.", + "excerpt_sha256": "932b0b9663759fcdd73a9a674b3a668c4137418ec06144f7bd3612168d61abab" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Content Slide layout with title `Design System Audit`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 19 + }, + { + "requirement_id": "slide-19.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must use the deck-level tokens exactly: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule.", + "provenance": { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "line_start": 10, + "line_end": 10, + "excerpt": "- Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must use the deck-level tokens exactly: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule.", + "excerpt_sha256": "c66f5647197b8988b7601e59373d92f9a8d5d5b8a5e49c102d4a4ca176907555" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must use the deck-level tokens exactly: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 19 + }, + { + "requirement_id": "slide-19.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Create two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs.", + "provenance": { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Create two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs.", + "excerpt_sha256": "807869dabb006a6b3b0f41fa79dc92766f59f1a4695107af79051f0856a9540a" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Create two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 19 + }, + { + "requirement_id": "slide-19.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes.", + "provenance": { + "source_id": "slide-19-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes.", + "excerpt_sha256": "0c629b54e3bfeb7b2f3e4e28a3c578ec2b673488c29561acbd21bc10ae750e81" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "structural_semantic", + "normalization": "Match every named visible and structural property; do not infer from gold." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 19 + }, + { + "requirement_id": "slide-20.prompt-r001", + "scope": "slide", + "mandatory": true, + "statement": "Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 5, + "line_end": 5, + "excerpt": "Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide.", + "excerpt_sha256": "1fc756e2b1db463a46cc92fe592b8bcbcf595a6bc7241d0944aa3919d11f2bae" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Everything combined: chart (line chart), table (3×6), approved image (cropped), Arabic + Japanese text, rotated text box at 45°, overlapping semi-transparent shapes, nested group, master-inherited footer, gradient fill, bullet list, slide number field — all on one slide.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + }, + { + "requirement_id": "slide-20.prompt-r002", + "scope": "slide", + "mandatory": true, + "statement": "Use the Blank with Footer layout with title `AcidSlide Synthesis`.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 11, + "line_end": 11, + "excerpt": "- Use the **Blank with Footer** layout with title `AcidSlide Synthesis`.", + "excerpt_sha256": "448b277d4919309f0b2c89c31fd4ed26bfe432ec53d74bbb493e876f8af9eda4" + }, + "severity": "major", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Use the Blank with Footer layout with title `AcidSlide Synthesis`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + }, + { + "requirement_id": "slide-20.prompt-r003", + "scope": "slide", + "mandatory": true, + "statement": "Add one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 12, + "line_end": 12, + "excerpt": "- Add one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`.", + "excerpt_sha256": "c9290c0038e5213fd6ae2aec7690f705665911923945219b13544c29ce36c99b" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + }, + { + "requirement_id": "slide-20.prompt-r004", + "scope": "slide", + "mandatory": true, + "statement": "Add one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 13, + "line_end": 13, + "excerpt": "- Add one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`.", + "excerpt_sha256": "002dfc07ea3b536a91fb863588727de959fe95f3c9020ca0e766d2b0df28c028" + }, + "severity": "critical", + "source_of_truth": "ooxml", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Add one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + }, + { + "requirement_id": "slide-20.prompt-r005", + "scope": "slide", + "mandatory": true, + "statement": "Insert `hero-abstract.png` with a 20% left crop. Add Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 14, + "line_end": 14, + "excerpt": "- Insert `hero-abstract.png` with a 20% left crop. Add Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP.", + "excerpt_sha256": "393f213352644b945cbf5a9bd8587806259012cc36eca0c162e1322a26579589" + }, + "severity": "critical", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Insert `hero-abstract.png` with a 20% left crop. Add Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + }, + { + "requirement_id": "slide-20.prompt-r006", + "scope": "slide", + "mandatory": true, + "statement": "Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer.", + "provenance": { + "source_id": "slide-20-prompt", + "source_type": "prompt", + "line_start": 15, + "line_end": 15, + "excerpt": "- Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer.", + "excerpt_sha256": "641b7b5911d4964ef11e26e7ce454de8d7e7a0ca3cfd51785b79aca194f6aa64" + }, + "severity": "major", + "source_of_truth": "both", + "matching_policy": { + "mode": "exact", + "normalization": "Exact Unicode, numeric values, units, and named OOXML construct after only prompt-declared unit conversion." + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named by this clause." + ] + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": "Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer.", + "automation_status": "unimplemented" + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [] + }, + "review_status": "pending", + "slide": 20 + } + ] +} diff --git a/acidslide-v1/benchmark/requirements/scored-assertion-inventory.json b/acidslide-v1/benchmark/requirements/scored-assertion-inventory.json new file mode 100644 index 0000000..5087032 --- /dev/null +++ b/acidslide-v1/benchmark/requirements/scored-assertion-inventory.json @@ -0,0 +1,7373 @@ +{ + "schema_version": "1.0", + "inventory_id": "acidslide-scored-assertion-inventory-v1", + "lifecycle_state": "candidate", + "benchmark_version": "acidslide-v1.0.0", + "prompt_bundle_sha256": "pending", + "reference_image_bundle_sha256": "pending", + "asset_manifest_sha256": "sha256:813a36b7e34fec686863e0d94ec4c040344b1c1a27270cdb103e424f988f4e8c", + "review": { + "status": "pending", + "reason": "Assertion provenance and fixture evidence are not independently approved." + }, + "assertions": [ + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-slide-count", + "checklist_item_id": "deck.slide-count", + "scope": "deck", + "tier": 1, + "statement": "The Level 3 deck contains exactly 20 ordered slides.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "exact_count": 20, + "selector": "slide_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-master-present", + "checklist_item_id": "deck.master-present", + "scope": "deck", + "tier": 1, + "statement": "At least one native slide master must own the shared background and footer elements.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "master", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "min_count": 1, + "selector": "master_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-font-policy", + "checklist_item_id": "deck.font-policy", + "scope": "deck", + "tier": 1, + "statement": "All rendered text uses the bundled font inventory.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-no-notes", + "checklist_item_id": "deck.no-notes", + "scope": "deck", + "tier": 1, + "statement": "The package contains no speaker notes or comments.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "no_notes" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-layouts-defined", + "checklist_item_id": "deck.layouts-defined", + "scope": "deck", + "tier": 1, + "statement": "Title Slide, Content Slide, Two-Column, and Blank with Footer layouts are defined.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "min_count": 4, + "selector": "layout_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-approved-assets", + "checklist_item_id": "deck.approved-assets", + "scope": "deck", + "tier": 1, + "statement": "Every required benchmark asset hash occurs in embedded media and no unapproved external media is introduced.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "ooxml", + "verification_method": "embedded_media_hash", + "expected_observation": { + "asset_hashes": { + "hero-abstract": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007", + "cityscape": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "texture-pattern": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385" + }, + "selector": "asset_manifest" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-native-slide-numbers", + "checklist_item_id": "deck.native-slide-numbers", + "scope": "deck", + "tier": 1, + "statement": "Slide numbers originate in the master/layout field rather than copied local text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "field", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "min_count": 1, + "selector": "master_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-ordered-tier-prefix", + "checklist_item_id": "deck.ordered-tier-prefix", + "scope": "deck", + "tier": 1, + "statement": "Level 1 and Level 2 remain ordered prefixes of the 20-slide Level 3 deck.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "exact_count": 20, + "selector": "slide_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-theme-structure", + "checklist_item_id": "deck.theme-structure", + "scope": "deck", + "tier": 2, + "statement": "Theme-driven colors and local overrides remain distinct in OOXML across the deck.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "min_count": 1, + "selector": "master_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-native-object-coverage", + "checklist_item_id": "deck.native-object-coverage", + "scope": "deck", + "tier": 2, + "statement": "The deck contains native charts, tables, fields, connectors, groups, placeholders, and pictures where prompted.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "exact_count": 20, + "selector": "slide_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-rtl-cjk-coverage", + "checklist_item_id": "deck.rtl-cjk-coverage", + "scope": "deck", + "tier": 2, + "statement": "Arabic RTL and Japanese CJK content remain editable and correctly encoded.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "exact_count": 20, + "selector": "slide_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-render-consistency", + "checklist_item_id": "deck.render-consistency", + "scope": "deck", + "tier": 1, + "statement": "All slide exports pass the official SSIM threshold against their corresponding gold exports.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-master-visual-consistency", + "checklist_item_id": "deck.master-visual-consistency", + "scope": "deck", + "tier": 1, + "statement": "The shared footer line, company label, and slide number align identically across applicable slides.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "footer", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-palette-consistency", + "checklist_item_id": "deck.palette-consistency", + "scope": "deck", + "tier": 1, + "statement": "Repeated palette roles render consistently across all 20 slides.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-typography-consistency", + "checklist_item_id": "deck.typography-consistency", + "scope": "deck", + "tier": 1, + "statement": "Repeated type roles render with the same family, size, weight, and color throughout the deck.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-spacing-consistency", + "checklist_item_id": "deck.spacing-consistency", + "scope": "deck", + "tier": 2, + "statement": "Repeated margins, gutters, and title anchors align across slide layouts.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "spacing", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-cross-slide-hierarchy", + "checklist_item_id": "deck.cross-slide-hierarchy", + "scope": "deck", + "tier": 3, + "statement": "Title, body, focal, and footer hierarchy remains structurally and visually consistent.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "both", + "verification_method": "layout_check", + "expected_observation": { + "min_count": 1, + "selector": "master_count" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-line-weight-detail", + "checklist_item_id": "deck.line-weight-detail", + "scope": "deck", + "tier": 3, + "statement": "Master rules, separators, borders, and connectors use the specified weights.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "line_weights", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-effect-detail", + "checklist_item_id": "deck.effect-detail", + "scope": "deck", + "tier": 3, + "statement": "Shadows, transparency, gradients, and patterns render consistently where repeated.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "effects", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "deck.assert-alignment-detail", + "checklist_item_id": "deck.alignment-detail", + "scope": "deck", + "tier": 3, + "statement": "Common title, footer, and grid anchors remain aligned throughout the deck.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "alignment", + "selector": "all_slides" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-key-text", + "checklist_item_id": "slide-01.key-text", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The slide must preserve the exact key text `AcidSlide v1` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "AcidSlide v1", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-native-primary", + "checklist_item_id": "slide-01.native-primary", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The primary structural requirement is one approved hero image with a 20% left crop; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "ooxml", + "verification_method": "embedded_media_hash", + "expected_observation": { + "asset_id": "hero-abstract", + "sha256": "63cab1432d0b4d8ab581c42b26d35e02ec28c32ada2e15267fd7eac760c04007", + "selector": "approved_asset" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-layout-binding", + "checklist_item_id": "slide-01.layout-binding", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The slide must be bound to the `Title Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-font-policy", + "checklist_item_id": "slide-01.font-policy", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-composition", + "checklist_item_id": "slide-01.composition", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The slide composition must include three overlapping translucent rounded rectangles.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-full-slide-fidelity", + "checklist_item_id": "slide-01.full-slide-fidelity", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-focal-fidelity", + "checklist_item_id": "slide-01.focal-fidelity", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The full-slide SSIM gate must preserve the appearance of the right-half hero image and title lockup; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the right-half hero image and title lockup", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-hierarchy-z-order", + "checklist_item_id": "slide-01.hierarchy-z-order", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "Preserve the specified Rectangle C, Rectangle A, hero, Rectangle B, title, subtitle z-order in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-semantic-structure", + "checklist_item_id": "slide-01.semantic-structure", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The editable object graph must express one approved hero image with a 20% left crop while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "picture" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-palette", + "checklist_item_id": "slide-01.palette", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-typography", + "checklist_item_id": "slide-01.typography", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-spacing", + "checklist_item_id": "slide-01.spacing", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-01.assert-decorative-detail", + "checklist_item_id": "slide-01.decorative-detail", + "scope": "slide", + "slide": 1, + "tier": 1, + "statement": "Preserve the hero outer shadow and rounded-rectangle transparency as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-key-text", + "checklist_item_id": "slide-02.key-text", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The slide must preserve the exact key text `Agenda` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Agenda", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-native-primary", + "checklist_item_id": "slide-02.native-primary", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The primary structural requirement is one native group containing the three icon-time rows; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "required": true, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-layout-binding", + "checklist_item_id": "slide-02.layout-binding", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-font-policy", + "checklist_item_id": "slide-02.font-policy", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-composition", + "checklist_item_id": "slide-02.composition", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The slide composition must include the agenda placeholder plus three circle/time rows.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 7, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-full-slide-fidelity", + "checklist_item_id": "slide-02.full-slide-fidelity", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-focal-fidelity", + "checklist_item_id": "slide-02.focal-fidelity", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The full-slide SSIM gate must preserve the appearance of the agenda body and aligned time column; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the agenda body and aligned time column", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-hierarchy-z-order", + "checklist_item_id": "slide-02.hierarchy-z-order", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "Preserve two bullet levels and the grouped time-column relationship in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 7, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-semantic-structure", + "checklist_item_id": "slide-02.semantic-structure", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The editable object graph must express one native group containing the three icon-time rows while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-palette", + "checklist_item_id": "slide-02.palette", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-typography", + "checklist_item_id": "slide-02.typography", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-spacing", + "checklist_item_id": "slide-02.spacing", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-02.assert-decorative-detail", + "checklist_item_id": "slide-02.decorative-detail", + "scope": "slide", + "slide": 2, + "tier": 1, + "statement": "Preserve bullet indents, line spacing, and paragraph spacing as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 7, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-key-text", + "checklist_item_id": "slide-03.key-text", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The slide must preserve the exact key text `Performance Metrics` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Performance Metrics", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-native-primary", + "checklist_item_id": "slide-03.native-primary", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The primary structural requirement is one native 7-by-5 OOXML table; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "table", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "required": true, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-layout-binding", + "checklist_item_id": "slide-03.layout-binding", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-font-policy", + "checklist_item_id": "slide-03.font-policy", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-composition", + "checklist_item_id": "slide-03.composition", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The slide composition must include the native table, annotation callout, and connector.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-full-slide-fidelity", + "checklist_item_id": "slide-03.full-slide-fidelity", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-focal-fidelity", + "checklist_item_id": "slide-03.focal-fidelity", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The full-slide SSIM gate must preserve the appearance of the full metrics table and throughput callout; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the full metrics table and throughput callout", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-hierarchy-z-order", + "checklist_item_id": "slide-03.hierarchy-z-order", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "Preserve header, alternating rows, conditional target colors, and mixed border weights in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-semantic-structure", + "checklist_item_id": "slide-03.semantic-structure", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The editable object graph must express one native 7-by-5 OOXML table while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "table", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-palette", + "checklist_item_id": "slide-03.palette", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-typography", + "checklist_item_id": "slide-03.typography", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-spacing", + "checklist_item_id": "slide-03.spacing", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-03.assert-decorative-detail", + "checklist_item_id": "slide-03.decorative-detail", + "scope": "slide", + "slide": 3, + "tier": 1, + "statement": "Preserve cell padding and the 0.5cm paragraph indent as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-key-text", + "checklist_item_id": "slide-04.key-text", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The slide must preserve the exact key text `Revenue Growth` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Revenue Growth", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-native-primary", + "checklist_item_id": "slide-04.native-primary", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The primary structural requirement is one native clustered horizontal bar chart with the supplied data; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "required": true, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-layout-binding", + "checklist_item_id": "slide-04.layout-binding", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-font-policy", + "checklist_item_id": "slide-04.font-policy", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-composition", + "checklist_item_id": "slide-04.composition", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The slide composition must include the chart, two callouts, connectors, and takeaway block.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-full-slide-fidelity", + "checklist_item_id": "slide-04.full-slide-fidelity", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-focal-fidelity", + "checklist_item_id": "slide-04.focal-fidelity", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The full-slide SSIM gate must preserve the appearance of the chart plot and overlaid YoY annotations; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the chart plot and overlaid YoY annotations", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-hierarchy-z-order", + "checklist_item_id": "slide-04.hierarchy-z-order", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "Preserve the chart-to-callout connector and overlay relationships in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-semantic-structure", + "checklist_item_id": "slide-04.semantic-structure", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The editable object graph must express one native clustered horizontal bar chart with the supplied data while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-palette", + "checklist_item_id": "slide-04.palette", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-typography", + "checklist_item_id": "slide-04.typography", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-spacing", + "checklist_item_id": "slide-04.spacing", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-04.assert-decorative-detail", + "checklist_item_id": "slide-04.decorative-detail", + "scope": "slide", + "slide": 4, + "tier": 1, + "statement": "Preserve legend, gridline, axis-label, and transparent-background styling as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-key-text", + "checklist_item_id": "slide-05.key-text", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The slide must preserve the exact key text `Our Team` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Our Team", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-native-primary", + "checklist_item_id": "slide-05.native-primary", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The primary structural requirement is three grouped team-member cards; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "required": true, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-layout-binding", + "checklist_item_id": "slide-05.layout-binding", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-font-policy", + "checklist_item_id": "slide-05.font-policy", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-composition", + "checklist_item_id": "slide-05.composition", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The slide composition must include three equally sized and distributed cards.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 12, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-full-slide-fidelity", + "checklist_item_id": "slide-05.full-slide-fidelity", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-focal-fidelity", + "checklist_item_id": "slide-05.focal-fidelity", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The full-slide SSIM gate must preserve the appearance of the three-card team composition; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-card team composition", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-hierarchy-z-order", + "checklist_item_id": "slide-05.hierarchy-z-order", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "Preserve footer, accent bar, company name, and number inherited rather than copied in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 12, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-semantic-structure", + "checklist_item_id": "slide-05.semantic-structure", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The editable object graph must express three grouped team-member cards while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-palette", + "checklist_item_id": "slide-05.palette", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-typography", + "checklist_item_id": "slide-05.typography", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-spacing", + "checklist_item_id": "slide-05.spacing", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-05.assert-decorative-detail", + "checklist_item_id": "slide-05.decorative-detail", + "scope": "slide", + "slide": 5, + "tier": 1, + "statement": "Preserve card border, circle, typography, and equal spacing as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 12, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-key-text", + "checklist_item_id": "slide-06.key-text", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The slide must preserve the exact key text `Global Perspectives` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Global Perspectives", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-native-primary", + "checklist_item_id": "slide-06.native-primary", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The primary structural requirement is English, Arabic RTL, and Japanese text boxes plus the overlapping callout; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-layout-binding", + "checklist_item_id": "slide-06.layout-binding", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-font-policy", + "checklist_item_id": "slide-06.font-policy", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-composition", + "checklist_item_id": "slide-06.composition", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The slide composition must include three editorial columns, two separators, and one callout.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-full-slide-fidelity", + "checklist_item_id": "slide-06.full-slide-fidelity", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-focal-fidelity", + "checklist_item_id": "slide-06.focal-fidelity", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the three-script editorial region; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-script editorial region", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-hierarchy-z-order", + "checklist_item_id": "slide-06.hierarchy-z-order", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "Preserve RTL paragraph direction, CJK line breaking, and callout overlap in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-semantic-structure", + "checklist_item_id": "slide-06.semantic-structure", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The editable object graph must express English, Arabic RTL, and Japanese text boxes plus the overlapping callout while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-palette", + "checklist_item_id": "slide-06.palette", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-typography", + "checklist_item_id": "slide-06.typography", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-spacing", + "checklist_item_id": "slide-06.spacing", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-06.assert-decorative-detail", + "checklist_item_id": "slide-06.decorative-detail", + "scope": "slide", + "slide": 6, + "tier": 2, + "statement": "Preserve separator opacity and script-specific font assignment as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-key-text", + "checklist_item_id": "slide-07.key-text", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The slide must preserve the exact key text `Image Handling` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Image Handling", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-native-primary", + "checklist_item_id": "slide-07.native-primary", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The primary structural requirement is three approved image instances with distinct crops and masks; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "ooxml", + "verification_method": "embedded_media_hash", + "expected_observation": { + "asset_id": "cityscape", + "sha256": "9b79bd07fd1bc22459fe6940754348c023182caba7f3ae4239a81c91db4e1a8a", + "selector": "approved_asset" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-layout-binding", + "checklist_item_id": "slide-07.layout-binding", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-font-policy", + "checklist_item_id": "slide-07.font-policy", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-composition", + "checklist_item_id": "slide-07.composition", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The slide composition must include three pictures, three captions, title, and PREVIEW overlay.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-full-slide-fidelity", + "checklist_item_id": "slide-07.full-slide-fidelity", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-focal-fidelity", + "checklist_item_id": "slide-07.focal-fidelity", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the three-image crop comparison; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the three-image crop comparison", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-hierarchy-z-order", + "checklist_item_id": "slide-07.hierarchy-z-order", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "Preserve the overlay above Image B and the picture-to-caption relationships in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-semantic-structure", + "checklist_item_id": "slide-07.semantic-structure", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The editable object graph must express three approved image instances with distinct crops and masks while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "picture" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-palette", + "checklist_item_id": "slide-07.palette", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-typography", + "checklist_item_id": "slide-07.typography", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-spacing", + "checklist_item_id": "slide-07.spacing", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-07.assert-decorative-detail", + "checklist_item_id": "slide-07.decorative-detail", + "scope": "slide", + "slide": 7, + "tier": 2, + "statement": "Preserve ellipse mask, rounded mask, crops, and italic captions as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-key-text", + "checklist_item_id": "slide-08.key-text", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The slide must preserve the exact key text `Depth & Layering` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Depth & Layering", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-native-primary", + "checklist_item_id": "slide-08.native-primary", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The primary structural requirement is two selective groups containing the five cards; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "required": true, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-layout-binding", + "checklist_item_id": "slide-08.layout-binding", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-font-policy", + "checklist_item_id": "slide-08.font-policy", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-composition", + "checklist_item_id": "slide-08.composition", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The slide composition must include five cards plus one full-width gradient strip.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-full-slide-fidelity", + "checklist_item_id": "slide-08.full-slide-fidelity", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-focal-fidelity", + "checklist_item_id": "slide-08.focal-fidelity", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the cascading five-card stack; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the cascading five-card stack", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-hierarchy-z-order", + "checklist_item_id": "slide-08.hierarchy-z-order", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "Preserve Card 1 through Card 5 z-order with only the requested subgrouping in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-semantic-structure", + "checklist_item_id": "slide-08.semantic-structure", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The editable object graph must express two selective groups containing the five cards while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-palette", + "checklist_item_id": "slide-08.palette", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-typography", + "checklist_item_id": "slide-08.typography", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-spacing", + "checklist_item_id": "slide-08.spacing", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-08.assert-decorative-detail", + "checklist_item_id": "slide-08.decorative-detail", + "scope": "slide", + "slide": 8, + "tier": 2, + "statement": "Preserve per-card opacity, outer shadow, and bottom gradient as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-key-text", + "checklist_item_id": "slide-09.key-text", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The slide must preserve the exact key text `API Reference` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "API Reference", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-native-primary", + "checklist_item_id": "slide-09.native-primary", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The primary structural requirement is two dense monospaced text boxes with different autofit modes; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "editability", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-layout-binding", + "checklist_item_id": "slide-09.layout-binding", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-font-policy", + "checklist_item_id": "slide-09.font-policy", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-composition", + "checklist_item_id": "slide-09.composition", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The slide composition must include two code columns and their labels.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-full-slide-fidelity", + "checklist_item_id": "slide-09.full-slide-fidelity", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-focal-fidelity", + "checklist_item_id": "slide-09.focal-fidelity", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the paired fixed-size and auto-shrink columns; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the paired fixed-size and auto-shrink columns", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-hierarchy-z-order", + "checklist_item_id": "slide-09.hierarchy-z-order", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "Preserve left clipping versus right auto-shrink semantics in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-semantic-structure", + "checklist_item_id": "slide-09.semantic-structure", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The editable object graph must express two dense monospaced text boxes with different autofit modes while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "editability", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-palette", + "checklist_item_id": "slide-09.palette", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-typography", + "checklist_item_id": "slide-09.typography", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-spacing", + "checklist_item_id": "slide-09.spacing", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-09.assert-decorative-detail", + "checklist_item_id": "slide-09.decorative-detail", + "scope": "slide", + "slide": 9, + "tier": 2, + "statement": "Preserve 1.15 line spacing and exact indentation as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-key-text", + "checklist_item_id": "slide-10.key-text", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The slide must preserve the exact key text `System Architecture` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "System Architecture", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-native-primary", + "checklist_item_id": "slide-10.native-primary", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The primary structural requirement is seven native connectors with destination arrowheads; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 7, + "required": true, + "selector": "connector" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-layout-binding", + "checklist_item_id": "slide-10.layout-binding", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-font-policy", + "checklist_item_id": "slide-10.font-policy", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-composition", + "checklist_item_id": "slide-10.composition", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The slide composition must include three nested groups covering processing, persistence, and backend.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-full-slide-fidelity", + "checklist_item_id": "slide-10.full-slide-fidelity", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-focal-fidelity", + "checklist_item_id": "slide-10.focal-fidelity", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the centered architecture network; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the centered architecture network", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-hierarchy-z-order", + "checklist_item_id": "slide-10.hierarchy-z-order", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "Preserve connector attachment, routing, and three-level backend grouping in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-semantic-structure", + "checklist_item_id": "slide-10.semantic-structure", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The editable object graph must express seven native connectors with destination arrowheads while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 7, + "selector": "connector" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-palette", + "checklist_item_id": "slide-10.palette", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-typography", + "checklist_item_id": "slide-10.typography", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-spacing", + "checklist_item_id": "slide-10.spacing", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-10.assert-decorative-detail", + "checklist_item_id": "slide-10.decorative-detail", + "scope": "slide", + "slide": 10, + "tier": 2, + "statement": "Preserve dashed group borders and connector labels as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-key-text", + "checklist_item_id": "slide-11.key-text", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The slide must preserve the exact key text `Brand Colors` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Brand Colors", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-native-primary", + "checklist_item_id": "slide-11.native-primary", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The primary structural requirement is six swatches split between theme references and explicit RGB overrides; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-layout-binding", + "checklist_item_id": "slide-11.layout-binding", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-font-policy", + "checklist_item_id": "slide-11.font-policy", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-composition", + "checklist_item_id": "slide-11.composition", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The slide composition must include six swatches, six labels, and explanatory copy.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-full-slide-fidelity", + "checklist_item_id": "slide-11.full-slide-fidelity", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-focal-fidelity", + "checklist_item_id": "slide-11.focal-fidelity", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the two-row swatch comparison; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the two-row swatch comparison", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-hierarchy-z-order", + "checklist_item_id": "slide-11.hierarchy-z-order", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "Preserve theme scheme colors in the top row versus fixed sRGB values below in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-semantic-structure", + "checklist_item_id": "slide-11.semantic-structure", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The editable object graph must express six swatches split between theme references and explicit RGB overrides while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-palette", + "checklist_item_id": "slide-11.palette", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-typography", + "checklist_item_id": "slide-11.typography", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-spacing", + "checklist_item_id": "slide-11.spacing", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-11.assert-decorative-detail", + "checklist_item_id": "slide-11.decorative-detail", + "scope": "slide", + "slide": 11, + "tier": 2, + "statement": "Preserve swatch sizing, label color, and row spacing as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-key-text", + "checklist_item_id": "slide-12.key-text", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The slide must preserve the exact key text `Document Fields` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Document Fields", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-native-primary", + "checklist_item_id": "slide-12.native-primary", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The primary structural requirement is native slide-number and fixed date/time fields; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "field", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "required": true, + "selector": "field" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-layout-binding", + "checklist_item_id": "slide-12.layout-binding", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-font-policy", + "checklist_item_id": "slide-12.font-policy", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-composition", + "checklist_item_id": "slide-12.composition", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The slide composition must include three field demonstrations, labels, and static comparison.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-full-slide-fidelity", + "checklist_item_id": "slide-12.full-slide-fidelity", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-focal-fidelity", + "checklist_item_id": "slide-12.focal-fidelity", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The full-slide SSIM gate must preserve the appearance of the field demonstration stack; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the field demonstration stack", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-hierarchy-z-order", + "checklist_item_id": "slide-12.hierarchy-z-order", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "Preserve live field runs and master footer versus static comparison text in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-semantic-structure", + "checklist_item_id": "slide-12.semantic-structure", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The editable object graph must express native slide-number and fixed date/time fields while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "field", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "field" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-palette", + "checklist_item_id": "slide-12.palette", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-typography", + "checklist_item_id": "slide-12.typography", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-spacing", + "checklist_item_id": "slide-12.spacing", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-12.assert-decorative-detail", + "checklist_item_id": "slide-12.decorative-detail", + "scope": "slide", + "slide": 12, + "tier": 2, + "statement": "Preserve field labels, comparison alignment, and footer placement as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-key-text", + "checklist_item_id": "slide-13.key-text", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The slide must preserve the exact key text `Composite Stress` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Composite Stress", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-native-primary", + "checklist_item_id": "slide-13.native-primary", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The primary structural requirement is one native six-segment pie chart; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "required": true, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-layout-binding", + "checklist_item_id": "slide-13.layout-binding", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-font-policy", + "checklist_item_id": "slide-13.font-policy", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-composition", + "checklist_item_id": "slide-13.composition", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The slide composition must include a native chart, native table, approved image, Arabic annotation, and three callouts.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-full-slide-fidelity", + "checklist_item_id": "slide-13.full-slide-fidelity", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-focal-fidelity", + "checklist_item_id": "slide-13.focal-fidelity", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the chart-table-image composite; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the chart-table-image composite", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-hierarchy-z-order", + "checklist_item_id": "slide-13.hierarchy-z-order", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "Preserve callouts layered over the composite without obscuring data in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-semantic-structure", + "checklist_item_id": "slide-13.semantic-structure", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The editable object graph must express one native six-segment pie chart while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-palette", + "checklist_item_id": "slide-13.palette", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-typography", + "checklist_item_id": "slide-13.typography", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-spacing", + "checklist_item_id": "slide-13.spacing", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-13.assert-decorative-detail", + "checklist_item_id": "slide-13.decorative-detail", + "scope": "slide", + "slide": 13, + "tier": 3, + "statement": "Preserve chart labels, table borders, image crop, and annotation styling as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-key-text", + "checklist_item_id": "slide-14.key-text", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The slide must preserve the exact key text `RTL Systems Review` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "RTL Systems Review", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-native-primary", + "checklist_item_id": "slide-14.native-primary", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The primary structural requirement is two long-form text columns containing Arabic, English, and bidirectional runs; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-layout-binding", + "checklist_item_id": "slide-14.layout-binding", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The slide must be bound to the `Two-Column` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-font-policy", + "checklist_item_id": "slide-14.font-policy", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-composition", + "checklist_item_id": "slide-14.composition", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The slide composition must include two mirrored editorial columns plus title and divider.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-full-slide-fidelity", + "checklist_item_id": "slide-14.full-slide-fidelity", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-focal-fidelity", + "checklist_item_id": "slide-14.focal-fidelity", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the Arabic-heavy left and English right comparison; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the Arabic-heavy left and English right comparison", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-hierarchy-z-order", + "checklist_item_id": "slide-14.hierarchy-z-order", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "Preserve native RTL direction and correct bidirectional run order in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-semantic-structure", + "checklist_item_id": "slide-14.semantic-structure", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The editable object graph must express two long-form text columns containing Arabic, English, and bidirectional runs while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 2, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-palette", + "checklist_item_id": "slide-14.palette", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-typography", + "checklist_item_id": "slide-14.typography", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-spacing", + "checklist_item_id": "slide-14.spacing", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-14.assert-decorative-detail", + "checklist_item_id": "slide-14.decorative-detail", + "scope": "slide", + "slide": 14, + "tier": 3, + "statement": "Preserve mirrored padding, divider, and script-specific typography as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 4, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-key-text", + "checklist_item_id": "slide-15.key-text", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The slide must preserve the exact key text `Rotation Atlas` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Rotation Atlas", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-native-primary", + "checklist_item_id": "slide-15.native-primary", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The primary structural requirement is five text boxes and five supporting shapes at the specified rotations; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 10, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-layout-binding", + "checklist_item_id": "slide-15.layout-binding", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-font-policy", + "checklist_item_id": "slide-15.font-policy", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-composition", + "checklist_item_id": "slide-15.composition", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The slide composition must include five label-and-shape pairs across a shared alignment grid.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 10, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-full-slide-fidelity", + "checklist_item_id": "slide-15.full-slide-fidelity", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-focal-fidelity", + "checklist_item_id": "slide-15.focal-fidelity", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the five-angle rotation sequence; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the five-angle rotation sequence", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-hierarchy-z-order", + "checklist_item_id": "slide-15.hierarchy-z-order", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "Preserve text and supporting shapes sharing exact rotation and anchor centers in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 10, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-semantic-structure", + "checklist_item_id": "slide-15.semantic-structure", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The editable object graph must express five text boxes and five supporting shapes at the specified rotations while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 10, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-palette", + "checklist_item_id": "slide-15.palette", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-typography", + "checklist_item_id": "slide-15.typography", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-spacing", + "checklist_item_id": "slide-15.spacing", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-15.assert-decorative-detail", + "checklist_item_id": "slide-15.decorative-detail", + "scope": "slide", + "slide": 15, + "tier": 3, + "statement": "Preserve rotation angles, anchor points, and line alignment as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 10, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-key-text", + "checklist_item_id": "slide-16.key-text", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The slide must preserve the exact key text `Beyond the Frame` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Beyond the Frame", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-native-primary", + "checklist_item_id": "slide-16.native-primary", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The primary structural requirement is three intentional bleed objects extending past left, top, and right edges; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-layout-binding", + "checklist_item_id": "slide-16.layout-binding", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-font-policy", + "checklist_item_id": "slide-16.font-policy", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-composition", + "checklist_item_id": "slide-16.composition", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The slide composition must include off-canvas circle, right-bleed rectangle, title, and two on-canvas labels.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-full-slide-fidelity", + "checklist_item_id": "slide-16.full-slide-fidelity", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-focal-fidelity", + "checklist_item_id": "slide-16.focal-fidelity", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the visible portions of the bleed objects; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the visible portions of the bleed objects", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-hierarchy-z-order", + "checklist_item_id": "slide-16.hierarchy-z-order", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "Preserve intentional negative coordinates retained without hidden-content cheating in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-semantic-structure", + "checklist_item_id": "slide-16.semantic-structure", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The editable object graph must express three intentional bleed objects extending past left, top, and right edges while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-palette", + "checklist_item_id": "slide-16.palette", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-typography", + "checklist_item_id": "slide-16.typography", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-spacing", + "checklist_item_id": "slide-16.spacing", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-16.assert-decorative-detail", + "checklist_item_id": "slide-16.decorative-detail", + "scope": "slide", + "slide": 16, + "tier": 3, + "statement": "Preserve edge clipping, opacity, and on-canvas label spacing as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-key-text", + "checklist_item_id": "slide-17.key-text", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The slide must preserve the exact key text `Nested Systems` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Nested Systems", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-native-primary", + "checklist_item_id": "slide-17.native-primary", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The primary structural requirement is at least six group objects spanning three nested levels; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "required": true, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-layout-binding", + "checklist_item_id": "slide-17.layout-binding", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-font-policy", + "checklist_item_id": "slide-17.font-policy", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-composition", + "checklist_item_id": "slide-17.composition", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The slide composition must include three hierarchy levels with 18 or more leaf shapes.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 18, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-full-slide-fidelity", + "checklist_item_id": "slide-17.full-slide-fidelity", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-focal-fidelity", + "checklist_item_id": "slide-17.focal-fidelity", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the centered nested-group assembly; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the centered nested-group assembly", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-hierarchy-z-order", + "checklist_item_id": "slide-17.hierarchy-z-order", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "Preserve outer, middle, and inner group transforms with preserved z-order in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 18, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-semantic-structure", + "checklist_item_id": "slide-17.semantic-structure", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The editable object graph must express at least six group objects spanning three nested levels while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 6, + "selector": "group" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-palette", + "checklist_item_id": "slide-17.palette", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-typography", + "checklist_item_id": "slide-17.typography", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-spacing", + "checklist_item_id": "slide-17.spacing", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-17.assert-decorative-detail", + "checklist_item_id": "slide-17.decorative-detail", + "scope": "slide", + "slide": 17, + "tier": 3, + "statement": "Preserve group borders, internal spacing, and label alignment as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 18, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-key-text", + "checklist_item_id": "slide-18.key-text", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The slide must preserve the exact key text `Three Cities / 三つの都市` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Three Cities / 三つの都市", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-native-primary", + "checklist_item_id": "slide-18.native-primary", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The primary structural requirement is three approved header-image instances, one per editorial column; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "ooxml", + "verification_method": "embedded_media_hash", + "expected_observation": { + "asset_id": "texture-pattern", + "sha256": "4417783162291de4024dd0ea2481b85b61955ad6cc8dc3684436f40009645385", + "selector": "approved_asset" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-layout-binding", + "checklist_item_id": "slide-18.layout-binding", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-font-policy", + "checklist_item_id": "slide-18.font-policy", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-composition", + "checklist_item_id": "slide-18.composition", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The slide composition must include three columns with images, body copy, and pull quotes.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-full-slide-fidelity", + "checklist_item_id": "slide-18.full-slide-fidelity", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-focal-fidelity", + "checklist_item_id": "slide-18.focal-fidelity", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the magazine-style three-column spread; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the magazine-style three-column spread", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-hierarchy-z-order", + "checklist_item_id": "slide-18.hierarchy-z-order", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "Preserve column-local image, copy, and quote relationships in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-semantic-structure", + "checklist_item_id": "slide-18.semantic-structure", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The editable object graph must express three approved header-image instances, one per editorial column while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "asset_identity", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 3, + "selector": "picture" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-palette", + "checklist_item_id": "slide-18.palette", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-typography", + "checklist_item_id": "slide-18.typography", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-spacing", + "checklist_item_id": "slide-18.spacing", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-18.assert-decorative-detail", + "checklist_item_id": "slide-18.decorative-detail", + "scope": "slide", + "slide": 18, + "tier": 3, + "statement": "Preserve the patterned center column and consistent gutters as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 9, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-key-text", + "checklist_item_id": "slide-19.key-text", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The slide must preserve the exact key text `Design System Audit` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "Design System Audit", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-native-primary", + "checklist_item_id": "slide-19.native-primary", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The primary structural requirement is five repeated design-system samples including two internal hyperlinks; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "required": true, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-layout-binding", + "checklist_item_id": "slide-19.layout-binding", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The slide must be bound to the `Content Slide` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "placeholder_type": "title", + "min_count": 1, + "selector": "placeholder" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-font-policy", + "checklist_item_id": "slide-19.font-policy", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-composition", + "checklist_item_id": "slide-19.composition", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The slide composition must include master-accurate samples for typography, colors, spacing, lines, and navigation.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 8, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-full-slide-fidelity", + "checklist_item_id": "slide-19.full-slide-fidelity", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-focal-fidelity", + "checklist_item_id": "slide-19.focal-fidelity", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the design-token audit grid; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the design-token audit grid", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-hierarchy-z-order", + "checklist_item_id": "slide-19.hierarchy-z-order", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "Preserve internal links target Slides 1 and 5 while master elements remain inherited in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 8, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-semantic-structure", + "checklist_item_id": "slide-19.semantic-structure", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The editable object graph must express five repeated design-system samples including two internal hyperlinks while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "theme", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 5, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-palette", + "checklist_item_id": "slide-19.palette", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-typography", + "checklist_item_id": "slide-19.typography", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-spacing", + "checklist_item_id": "slide-19.spacing", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-19.assert-decorative-detail", + "checklist_item_id": "slide-19.decorative-detail", + "scope": "slide", + "slide": 19, + "tier": 3, + "statement": "Preserve exact token values and equal sample spacing as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 8, + "selector": "shape" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-key-text", + "checklist_item_id": "slide-20.key-text", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The slide must preserve the exact key text `AcidSlide Synthesis` as editable text.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "text_content", + "source_of_truth": "ooxml", + "verification_method": "text_match", + "expected_observation": { + "contains": "AcidSlide Synthesis", + "selector": "slide_text" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-native-primary", + "checklist_item_id": "slide-20.native-primary", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The primary structural requirement is one native line chart with three series; raster or shape imitations do not qualify.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "required": true, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-layout-binding", + "checklist_item_id": "slide-20.layout-binding", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The slide must be bound to the `Blank with Footer` master layout and use its required inherited content.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "layout", + "source_of_truth": "ooxml", + "verification_method": "layout_check", + "expected_observation": { + "required": true, + "selector": "master_ref" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-font-policy", + "checklist_item_id": "slide-20.font-policy", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "ooxml", + "verification_method": "anti_cheat", + "expected_observation": { + "selector": "font_policy" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-composition", + "checklist_item_id": "slide-20.composition", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The slide composition must include chart, 3-by-6 table, approved image, multilingual copy, rotation, groups, gradient, bullets, and fields.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-full-slide-fidelity", + "checklist_item_id": "slide-20.full-slide-fidelity", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-focal-fidelity", + "checklist_item_id": "slide-20.focal-fidelity", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The full-slide SSIM gate must preserve the appearance of the full final composite; this label identifies the diagnostic focal region.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic_region": "the full final composite", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-hierarchy-z-order", + "checklist_item_id": "slide-20.hierarchy-z-order", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "Preserve nested group, overlap stack, field, and master footer relationships in native OOXML and in the rendered result.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "native_structure", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-semantic-structure", + "checklist_item_id": "slide-20.semantic-structure", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The editable object graph must express one native line chart with three series while remaining visually equivalent to the reference.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "chart", + "source_of_truth": "both", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "chart" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-palette", + "checklist_item_id": "slide-20.palette", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_appearance", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "palette", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-typography", + "checklist_item_id": "slide-20.typography", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_typography", + "source_of_truth": "render", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "typography", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-spacing", + "checklist_item_id": "slide-20.spacing", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_spacing", + "source_of_truth": "both", + "verification_method": "visual_ssim", + "expected_observation": { + "min_ssim": 0.9999, + "diagnostic": "geometry", + "selector": "full_slide" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + }, + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": "slide-20.assert-decorative-detail", + "checklist_item_id": "slide-20.decorative-detail", + "scope": "slide", + "slide": 20, + "tier": 3, + "statement": "Preserve image crop, 45-degree label, gradient, bullet spacing, and multilingual typography as editable native detail.", + "provenance": { + "status": "pending", + "reason": "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + }, + "property_class": "visual_color", + "source_of_truth": "ooxml", + "verification_method": "object_compare", + "expected_observation": { + "min_count": 1, + "selector": "table" + }, + "evidence": { + "status": "pending", + "reason": "Positive, single-fault negative, and mutation evidence has not yet been observed." + }, + "gold_ooxml_is_oracle": false + } + ] +} diff --git a/acidslide-v1/benchmark/tools/build_corpus.py b/acidslide-v1/benchmark/tools/build_corpus.py new file mode 100644 index 0000000..61aea55 --- /dev/null +++ b/acidslide-v1/benchmark/tools/build_corpus.py @@ -0,0 +1,1490 @@ +#!/usr/bin/env python3 +# ruff: noqa: E501 +"""Build the deterministic, non-gold AcidSlide v1 benchmark corpus. + +This tool intentionally owns only prompts, prompt validation records, manifests, +checklist YAML, and the explicitly non-frozen scored-assertion candidate. It +never creates the gold deck, exports, evidence fixtures, baselines, approvals, +or service data. +""" + +from __future__ import annotations + +import hashlib +import json +import re +from dataclasses import dataclass +from pathlib import Path + +BENCHMARK = Path(__file__).resolve().parents[1] +PROMPTS = BENCHMARK / "prompts" + + +@dataclass(frozen=True) +class SlideSpec: + tier: int + name: str + key_text: str + layout: str + primary_selector: str + primary_count: int + primary_kind: str + primary_description: str + composition_selector: str + composition_count: int + composition: str + focal_region: str + hierarchy: str + decorative_detail: str + asset_id: str | None = None + + +SPECS: dict[int, SlideSpec] = { + 1: SlideSpec( + 1, + "Cover / Title Stress Test", + "AcidSlide v1", + "Title Slide", + "picture", + 1, + "image-asset", + "one approved hero image with a 20% left crop", + "shape", + 3, + "three overlapping translucent rounded rectangles", + "the right-half hero image and title lockup", + "the specified Rectangle C, Rectangle A, hero, Rectangle B, title, subtitle z-order", + "the hero outer shadow and rounded-rectangle transparency", + "hero-abstract", + ), + 2: SlideSpec( + 1, + "Dense Agenda with Layout Semantics", + "Agenda", + "Content Slide", + "group", + 1, + "grouping", + "one native group containing the three icon-time rows", + "shape", + 7, + "the agenda placeholder plus three circle/time rows", + "the agenda body and aligned time column", + "two bullet levels and the grouped time-column relationship", + "bullet indents, line spacing, and paragraph spacing", + ), + 3: SlideSpec( + 1, + "Native Table Stress Test", + "Performance Metrics", + "Blank with Footer", + "table", + 1, + "table", + "one native 7-by-5 OOXML table", + "shape", + 2, + "the native table, annotation callout, and connector", + "the full metrics table and throughput callout", + "header, alternating rows, conditional target colors, and mixed border weights", + "cell padding and the 0.5cm paragraph indent", + ), + 4: SlideSpec( + 1, + "Native Chart Stress Test", + "Revenue Growth", + "Content Slide", + "chart", + 1, + "chart", + "one native clustered horizontal bar chart with the supplied data", + "shape", + 3, + "the chart, two callouts, connectors, and takeaway block", + "the chart plot and overlaid YoY annotations", + "the chart-to-callout connector and overlay relationships", + "legend, gridline, axis-label, and transparent-background styling", + ), + 5: SlideSpec( + 1, + "Master Reuse Enforcement", + "Our Team", + "Content Slide", + "group", + 3, + "grouping", + "three grouped team-member cards", + "shape", + 12, + "three equally sized and distributed cards", + "the three-card team composition", + "footer, accent bar, company name, and number inherited rather than copied", + "card border, circle, typography, and equal spacing", + ), + 6: SlideSpec( + 2, + "Multilingual Editorial", + "Global Perspectives", + "Blank with Footer", + "shape", + 4, + "multilingual", + "English, Arabic RTL, and Japanese text boxes plus the overlapping callout", + "shape", + 6, + "three editorial columns, two separators, and one callout", + "the three-script editorial region", + "RTL paragraph direction, CJK line breaking, and callout overlap", + "separator opacity and script-specific font assignment", + ), + 7: SlideSpec( + 2, + "Image Crop and Mask", + "Image Handling", + "Blank with Footer", + "picture", + 3, + "image-asset", + "three approved image instances with distinct crops and masks", + "shape", + 5, + "three pictures, three captions, title, and PREVIEW overlay", + "the three-image crop comparison", + "the overlay above Image B and the picture-to-caption relationships", + "ellipse mask, rounded mask, crops, and italic captions", + "cityscape", + ), + 8: SlideSpec( + 2, + "Overlap, Shadow, and Transparency", + "Depth & Layering", + "Blank with Footer", + "group", + 2, + "grouping", + "two selective groups containing the five cards", + "shape", + 6, + "five cards plus one full-width gradient strip", + "the cascading five-card stack", + "Card 1 through Card 5 z-order with only the requested subgrouping", + "per-card opacity, outer shadow, and bottom gradient", + ), + 9: SlideSpec( + 2, + "Dense Text Overflow", + "API Reference", + "Content Slide", + "shape", + 2, + "overflow", + "two dense monospaced text boxes with different autofit modes", + "shape", + 4, + "two code columns and their labels", + "the paired fixed-size and auto-shrink columns", + "left clipping versus right auto-shrink semantics", + "1.15 line spacing and exact indentation", + ), + 10: SlideSpec( + 2, + "Connector and Alignment Diagram", + "System Architecture", + "Blank with Footer", + "connector", + 7, + "structure", + "seven native connectors with destination arrowheads", + "group", + 3, + "three nested groups covering processing, persistence, and backend", + "the centered architecture network", + "connector attachment, routing, and three-level backend grouping", + "dashed group borders and connector labels", + ), + 11: SlideSpec( + 2, + "Theme vs Local Override", + "Brand Colors", + "Content Slide", + "shape", + 6, + "theme-consistency", + "six swatches split between theme references and explicit RGB overrides", + "shape", + 9, + "six swatches, six labels, and explanatory copy", + "the two-row swatch comparison", + "theme scheme colors in the top row versus fixed sRGB values below", + "swatch sizing, label color, and row spacing", + ), + 12: SlideSpec( + 2, + "Native Field Slide", + "Document Fields", + "Content Slide", + "field", + 2, + "fields", + "native slide-number and fixed date/time fields", + "shape", + 6, + "three field demonstrations, labels, and static comparison", + "the field demonstration stack", + "live field runs and master footer versus static comparison text", + "field labels, comparison alignment, and footer placement", + ), + 13: SlideSpec( + 3, + "Composite Stress", + "Composite Stress", + "Blank with Footer", + "chart", + 1, + "chart", + "one native six-segment pie chart", + "table", + 1, + "a native chart, native table, approved image, Arabic annotation, and three callouts", + "the chart-table-image composite", + "callouts layered over the composite without obscuring data", + "chart labels, table borders, image crop, and annotation styling", + "cityscape", + ), + 14: SlideSpec( + 3, + "RTL-Heavy Comparison", + "RTL Systems Review", + "Two-Column", + "shape", + 2, + "multilingual", + "two long-form text columns containing Arabic, English, and bidirectional runs", + "shape", + 4, + "two mirrored editorial columns plus title and divider", + "the Arabic-heavy left and English right comparison", + "native RTL direction and correct bidirectional run order", + "mirrored padding, divider, and script-specific typography", + ), + 15: SlideSpec( + 3, + "Rotated Text", + "Rotation Atlas", + "Blank with Footer", + "shape", + 10, + "structure", + "five text boxes and five supporting shapes at the specified rotations", + "shape", + 10, + "five label-and-shape pairs across a shared alignment grid", + "the five-angle rotation sequence", + "text and supporting shapes sharing exact rotation and anchor centers", + "rotation angles, anchor points, and line alignment", + ), + 16: SlideSpec( + 3, + "Intentional Off-Canvas Bleed", + "Beyond the Frame", + "Blank with Footer", + "shape", + 3, + "structure", + "three intentional bleed objects extending past left, top, and right edges", + "shape", + 5, + "off-canvas circle, right-bleed rectangle, title, and two on-canvas labels", + "the visible portions of the bleed objects", + "intentional negative coordinates retained without hidden-content cheating", + "edge clipping, opacity, and on-canvas label spacing", + ), + 17: SlideSpec( + 3, + "Deep Grouping", + "Nested Systems", + "Blank with Footer", + "group", + 6, + "grouping", + "at least six group objects spanning three nested levels", + "shape", + 18, + "three hierarchy levels with 18 or more leaf shapes", + "the centered nested-group assembly", + "outer, middle, and inner group transforms with preserved z-order", + "group borders, internal spacing, and label alignment", + ), + 18: SlideSpec( + 3, + "Multi-Column Editorial", + "Three Cities / 三つの都市", + "Blank with Footer", + "picture", + 3, + "image-asset", + "three approved header-image instances, one per editorial column", + "shape", + 9, + "three columns with images, body copy, and pull quotes", + "the magazine-style three-column spread", + "column-local image, copy, and quote relationships", + "the patterned center column and consistent gutters", + "texture-pattern", + ), + 19: SlideSpec( + 3, + "Repetition and Consistency", + "Design System Audit", + "Content Slide", + "shape", + 5, + "theme-consistency", + "five repeated design-system samples including two internal hyperlinks", + "shape", + 8, + "master-accurate samples for typography, colors, spacing, lines, and navigation", + "the design-token audit grid", + "internal links target Slides 1 and 5 while master elements remain inherited", + "exact token values and equal sample spacing", + ), + 20: SlideSpec( + 3, + "Final Torture Slide", + "AcidSlide Synthesis", + "Blank with Footer", + "chart", + 1, + "chart", + "one native line chart with three series", + "table", + 1, + "chart, 3-by-6 table, approved image, multilingual copy, rotation, groups, gradient, bullets, and fields", + "the full final composite", + "nested group, overlap stack, field, and master footer relationships", + "image crop, 45-degree label, gradient, bullet spacing, and multilingual typography", + "hero-abstract", + ), +} + + +LEVEL3_DETAILS = { + 13: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout and title the slide `Composite Stress` in Carlito 36pt Bold at (1.5cm, 0.5cm). +- Add one native pie chart at (1.5cm, 3cm), size 10cm × 8cm. Use six labeled values: `Structure 28`, `Text 22`, `Visual 18`, `Assets 14`, `Fields 10`, `Other 8`; show percentage labels and no legend. +- Add one native 4-row × 3-column table at (13cm, 3cm), size 9cm × 7cm. Header: `Check`, `Status`, `Weight`. Rows: `Schema | Pass | 3`, `Rendering | Pass | 2`, `Assets | Review | 1`. +- Insert `cityscape.png` at (23cm, 3cm), size 8cm × 6cm, cropping 15% from the left. Use only asset ID `cityscape` from the manifest. +- Add the Arabic annotation `الهيكل والمحتوى والعرض في اختبار واحد` in Noto Sans Arabic 14pt with native RTL direction. +- Add three dense rounded callouts labeled `NATIVE CHART`, `NATIVE TABLE`, and `APPROVED ASSET`; connect each to its target and keep all data labels visible. +""", + 14: """ +## Explicit v1 constraints + +- Use the **Two-Column** layout with title `RTL Systems Review`. +- The left column contains at least five separate Arabic paragraphs in Noto Sans Arabic 14pt with native RTL paragraph direction. Include these exact phrases: `مراجعة الأنظمة الموزعة`, `دقة العرض`, `سلامة البنية`, `The الذكاء الاصطناعي revolution`, and `الإصدار AcidSlide v1`. +- The right column contains five English summary paragraphs in Liberation Sans 14pt, beginning with `A structural benchmark must preserve meaning and direction.` +- Right-align the Arabic column and left-align the English column. Mirror their inner padding and keep a 1pt teal divider centered between them. +- Mixed Arabic/English runs must preserve Unicode character order and visible punctuation without converting text to outlines. +""", + 15: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Rotation Atlas`. +- Create five text boxes labeled exactly `Baseline 0°`, `Diagonal 45°`, `Vertical 90°`, `Reverse 135°`, and `Vertical 270°`. +- Apply rotations of 0°, 45°, 90°, 135°, and 270° respectively. Each text box is 5cm × 1.5cm, uses Liberation Sans 16pt Bold, and has a matching 6cm × 2cm supporting rectangle sharing its center and rotation. +- Distribute the five pairs evenly from x=2cm through x=28cm on a common y=8cm anchor line. Keep text editable and store rotations in native OOXML transforms. +""", + 16: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Beyond the Frame`. +- Place a 10cm diameter coral circle at (-3cm, -2cm), a 12cm × 6cm teal rectangle at (28.867cm, 6cm) so it extends 5cm beyond the right edge, and a 16cm × 3cm gold strip at (8cm, -1cm). +- Add on-canvas labels `INTENTIONAL BLEED` and `Negative coordinates are part of the composition.` +- Preserve negative and over-bound coordinates in OOXML. Do not replace the composition with a screenshot, hide content under opaque shapes, or move the objects fully on-canvas. +""", + 17: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Nested Systems`. +- Build one outer group containing three middle groups. Each middle group contains two inner groups; each inner group contains three leaf shapes (18 leaf shapes total). +- Use native group objects at all three levels. Label the middle groups `INPUT`, `PROCESS`, and `OUTPUT`; label inner groups `A1`, `A2`, `B1`, `B2`, `C1`, and `C2`. +- Within every inner group, z-order is circle below rounded rectangle below label. The full outer group's bounding box has top-left position (3cm, 3cm) and size 27cm × 13cm. +""", + 18: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `Three Cities / 三つの都市`. +- Build three equal 9.5cm-wide editorial columns with 0.9cm gutters. Each column contains a 9.5cm × 3.5cm approved header image, a heading, body copy, and a pull quote. +- Column images, left to right: `cityscape.png`, `texture-pattern.png`, `cityscape.png`. Center the crop of each image and do not use unlisted media. +- Headings: `Systems`, `システム`, `Shared Futures`. Include the exact Japanese line `生成されたスライドは構造と意味を保持します。` +- Apply the approved `texture-pattern.png` as a tiled background only to the center column at 20% opacity. Use 0.9cm gutters consistently. +""", + 19: """ +## Explicit v1 constraints + +- Use the **Content Slide** layout with title `Design System Audit`. +- Show five samples labeled `Typography`, `Palette`, `Spacing`, `Line Weight`, and `Navigation`. Each sample must use the deck-level tokens exactly: Carlito 36pt, Liberation Sans 18pt, navy `#1B2A4A`, coral `#E8634A`, teal `#2AACB8`, and a 0.5pt teal rule. +- Create two native internal hyperlinks: `Return to Cover` targets Slide 1 and `Meet the Team` targets Slide 5. Do not use external URLs. +- Footer line, company name, accent bar, and slide number remain inherited from the master/layout; do not duplicate them as slide-local shapes. +""", + 20: """ +## Explicit v1 constraints + +- Use the **Blank with Footer** layout with title `AcidSlide Synthesis`. +- Add one native line chart with series `Structural`, `Visual`, and `Combined` across categories `L1`, `L2`, `L3`; values are `72, 84, 96`, `68, 82, 95`, and `70, 83, 97`. +- Add one native 3-row × 6-column table. Header: `Tier`, `Slides`, `Checks`, `SSIM`, `Schema`, `Status`; rows: `L1 | 5 | 70 | 0.9999 | Pass | Ready` and `L3 | 20 | 280 | 0.9999 | Pass | Ready`. +- Insert `hero-abstract.png` with a 20% left crop. Add Arabic `اختبار شامل` with native RTL direction and Japanese `総合テスト` in Noto Sans CJK JP. +- Include a 45° text box labeled `ROTATED`, three overlapping semi-transparent shapes inside a two-level group, a navy-to-teal gradient, a three-item bullet list, a live slide-number field, and the inherited master footer. +""", +} + + +PARAPHRASE_A = { + "What to build": "Required construction", + "must contain": "is required to include", + "must use": "is required to use", + "MUST be": "must remain", + "MUST come": "must originate", + "should have": "needs", + "Do NOT": "Never", + "Tests ": "Evaluates ", + "Critical requirement": "Non-negotiable requirement", + "Explicit v1 constraints": "Mandatory v1 requirements", + "Use the": "Select the", + "Use only": "Rely exclusively on", + "Use ": "Employ ", + "Add ": "Include ", + "Insert ": "Place ", + "Create ": "Construct ", + "Apply ": "Set ", + "Keep ": "Ensure ", + "Place ": "Position ", + "Preserve ": "Retain ", + "positioned": "placed", + "containing": "that includes", + "exactly": "precisely", + "below": "under", + "above": "over", +} + +PARAPHRASE_B = { + "What to build": "Acceptance-target composition", + "must contain": "needs to contain", + "must use": "must employ", + "MUST be": "must be implemented as", + "MUST come": "must be inherited", + "should have": "is expected to have", + "Do NOT": "Do not ever", + "Tests ": "Measures ", + "Critical requirement": "Required invariant", + "Explicit v1 constraints": "Fixed v1 acceptance constraints", + "Use the": "Adopt the", + "Use only": "Rely exclusively on", + "Use ": "Choose ", + "Add ": "Provide ", + "Insert ": "Embed ", + "Create ": "Produce ", + "Apply ": "Assign ", + "Keep ": "Maintain ", + "Place ": "Set ", + "Preserve ": "Maintain ", + "positioned": "located", + "containing": "composed of", + "exactly": "with exact precision", + "below": "beneath", + "above": "over", +} + + +def sha256(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def paraphrase(text: str, replacements: dict[str, str], label: str) -> str: + protected: list[str] = [] + + def hide(match: re.Match[str]) -> str: + protected.append(match.group(0)) + return f"\x00PROTECTED_{len(protected) - 1}\x00" + + result = re.sub(r"```.*?```|`[^`\n]+`", hide, text, flags=re.DOTALL) + for source, replacement in replacements.items(): + result = result.replace(source, replacement) + result = re.sub( + r"^# AcidSlide v1 — Slide (\d{2}): (.+)$", + rf"# AcidSlide v1 — Slide \1: \2 ({label})", + result, + flags=re.MULTILINE, + ) + if label.endswith("A"): + result = re.sub( + r"The natural-language requirements .*?supplementary visual guidance\.", + "The natural-language requirements that follow are the primary directive. Treat the reference image as supplementary visual guidance only.", + result, + count=1, + ) + else: + result = re.sub( + r"The natural-language requirements .*?supplementary visual guidance\.", + "The primary directive is the following set of natural-language requirements. Consult the reference image solely for supplementary visual guidance.", + result, + count=1, + ) + for index, original in enumerate(protected): + result = result.replace(f"\x00PROTECTED_{index}\x00", original) + return result + + +def canonical_sections() -> dict[int, str]: + brief = (PROMPTS / "DESIGNER_BRIEF.md").read_text(encoding="utf-8") + sections: dict[int, str] = {} + starts = list(re.finditer(r"^### SLIDE (\d+): (.+)$", brief, re.MULTILINE)) + for index, match in enumerate(starts): + number = int(match.group(1)) + end = ( + starts[index + 1].start() + if index + 1 < len(starts) + else brief.find("\n## Asset Manifest", match.start()) + ) + body = brief[match.end() : end].strip() + heading = f"# AcidSlide v1 — Slide {number:02d}: {match.group(2)}" + intro = ( + "\n\nThe natural-language requirements below are the primary directive. " + "Use the reference image only as supplementary visual guidance.\n\n" + ) + content = heading + intro + body + if number in LEVEL3_DETAILS: + content += "\n\n" + LEVEL3_DETAILS[number].strip() + "\n" + sections[number] = content.strip() + "\n" + if set(sections) != set(range(1, 21)): + raise RuntimeError(f"expected slide sections 1-20, found {sorted(sections)}") + return sections + + +def write_prompts() -> None: + brief = (PROMPTS / "DESIGNER_BRIEF.md").read_text(encoding="utf-8") + deck_start = brief.index("## Critical Rules") + deck_end = brief.index("## Slide-by-Slide Instructions") + deck_body = brief[deck_start:deck_end].strip() + deck_prompt = ( + "# AcidSlide v1 — Deck-Level Prompt\n\n" + "This prompt is the primary deck-wide requirements contract. It is authored independently of the reference deck; " + "reference PNGs are supplementary guidance only. Build a new `.pptx` from these instructions in the pinned LibreOffice environment.\n\n" + + deck_body + + "\n" + ) + (PROMPTS / "deck.md").write_text(deck_prompt, encoding="utf-8") + + sections = canonical_sections() + for directory in ("canonical", "paraphrase-a", "paraphrase-b"): + (PROMPTS / "variants" / directory).mkdir(parents=True, exist_ok=True) + validation_dir = PROMPTS / "validation" + validation_dir.mkdir(parents=True, exist_ok=True) + + token_pattern = re.compile( + r"#[0-9A-Fa-f]{6}|[A-Za-z0-9_-]+\.(?:png|pptx)|\d+(?:\.\d+)?(?:cm|pt|px|mm|%|°|×)|`[^`\n]+`|\"[^\"\n]+\"|[\u0600-\u06ff]+|[\u3040-\u30ff\u3400-\u9fff]+" + ) + for number, canonical in sections.items(): + variant_a = paraphrase(canonical, PARAPHRASE_A, "alternative wording A") + variant_b = paraphrase(canonical, PARAPHRASE_B, "alternative wording B") + paths = { + "canonical": PROMPTS / "variants" / "canonical" / f"slide-{number:02d}.md", + "paraphrase-a": PROMPTS / "variants" / "paraphrase-a" / f"slide-{number:02d}.md", + "paraphrase-b": PROMPTS / "variants" / "paraphrase-b" / f"slide-{number:02d}.md", + } + texts = { + "canonical": canonical, + "paraphrase-a": variant_a, + "paraphrase-b": variant_b, + } + for key, path in paths.items(): + path.write_text(texts[key], encoding="utf-8") + canonical_tokens = sorted(token_pattern.findall(canonical)) + token_parity = all( + sorted(token_pattern.findall(text)) == canonical_tokens for text in texts.values() + ) + canonical_blocks = re.findall(r"```.*?```", canonical, re.DOTALL) + block_parity = all( + re.findall(r"```.*?```", text, re.DOTALL) == canonical_blocks for text in texts.values() + ) + parity = token_parity and block_parity + prompt_hashes = { + "canonical": f"sha256:{sha256(paths['canonical'])}", + "paraphrase-a": f"sha256:{sha256(paths['paraphrase-a'])}", + "paraphrase-b": f"sha256:{sha256(paths['paraphrase-b'])}", + } + metadata = { + "schema_version": "1.0", + "record_id": f"acidslide-prompt-validation-slide-{number:02d}", + "slide": number, + "prompt_hashes": prompt_hashes, + "status": "pending", + "round_id": None, + "authors": [], + "pairwise_similarity_diagnostics": [], + } + machine_record = json.dumps(metadata, indent=2, sort_keys=True) + record = f""" +# Slide {number:02d} prompt validation + +- Prompt contract status: complete +- Canonical/paraphrase hard-constraint parity: {"pass" if parity else "fail"} +- Canonical SHA-256: `{sha256(paths["canonical"])}` +- Paraphrase A SHA-256: `{sha256(paths["paraphrase-a"])}` +- Paraphrase B SHA-256: `{sha256(paths["paraphrase-b"])}` +- Independent-author convergence: not run +- Required blinded author count: 3 +- Mandatory assertion pass status: pending for all 3 implementations +- Structural similarity: diagnostic only; no release threshold +- Release gate: blocked until three clean-context authors independently build the slide and every mandatory assertion passes for every implementation; any failed assertion or author disagreement requires prompt/oracle revision and a fresh blinded round + +The static record verifies that literal text, asset filenames, colors, dimensions, percentages, rotations, and multilingual strings are preserved across all three prompt variants. It does not claim authoring convergence or gold-deck fidelity, and structural similarity cannot override a missed requirement. +""" + if not parity: + raise RuntimeError(f"hard-constraint drift in slide {number:02d} variants") + record_path = validation_dir / f"slide-{number:02d}.md" + if record_path.is_file(): + existing = record_path.read_text(encoding="utf-8") + match = re.match( + r"\A\n", + existing, + re.DOTALL, + ) + if match: + existing_metadata = json.loads(match.group(1)) + if existing_metadata.get("status") == "completed": + if existing_metadata.get("prompt_hashes") != prompt_hashes: + raise RuntimeError( + f"completed prompt-validation evidence for slide {number:02d} " + "was invalidated by prompt hash drift; archive and reset it explicitly" + ) + continue + record_path.write_text(record, encoding="utf-8") + + +def verification(method: str, selector: str = "", expectation: dict | None = None) -> dict: + data: dict = {"method": method} + if selector: + data["selector"] = selector + if expectation: + data["expectation"] = expectation + return data + + +def pending_checklist_metadata(item_id: str) -> dict: + """Return honest candidate metadata without fabricating frozen evidence.""" + prefix, suffix = item_id.split(".", maxsplit=1) + return { + "assertion_id": f"{prefix}.assert-{suffix}", + "provenance": { + "status": "pending", + "reason": "Independent atomic source mapping, immutable hash, locator, and provenance-kind review are not complete.", + }, + "evidence": { + "status": "pending", + "reason": "Independent positive, single-fault negative, and mutation evidence has not been authored and reviewed.", + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_expectation_ids": [], + }, + "lifecycle_state": "candidate", + } + + +def item( + number: int, + suffix: str, + title: str, + description: str, + kind: str, + severity: str, + source: str, + check: dict, + failure_mode: dict | None = None, +) -> dict: + result = { + "schema_version": "1.0", + "id": f"slide-{number:02d}.{suffix}", + "scope": "slide", + "slide": number, + "tier": SPECS[number].tier, + "title": title, + "description": description, + "kind": kind, + "severity": severity, + "source_of_truth": source, + "verification": check, + } + if failure_mode: + failure_mode = dict(failure_mode) + failure_mode["affected_slides"] = { + "status": "complete", + "mode": "current_slide", + "slides": [number], + "selector_id": None, + "selector_sha256": None, + } + result["failure_mode"] = failure_mode + result.update(pending_checklist_metadata(result["id"])) + return result + + +def slide_items(number: int, asset_hashes: dict[str, str]) -> list[dict]: + spec = SPECS[number] + primary_check = verification( + "object_compare", + spec.primary_selector, + {"min_count": spec.primary_count, "required": True}, + ) + if spec.primary_kind == "image-asset": + if spec.asset_id is None: + raise ValueError( + f"Slide {number} has an image-asset primary without an approved asset ID" + ) + primary_check = verification( + "hash_match", + "approved_asset", + {"asset_id": spec.asset_id, "sha256": asset_hashes[spec.asset_id]}, + ) + layout_check = verification("layout_check", "master_ref", {"required": True}) + if spec.layout in {"Title Slide", "Content Slide", "Two-Column"}: + layout_check = verification( + "layout_check", "placeholder", {"placeholder_type": "title", "min_count": 1} + ) + return [ + item( + number, + "key-text", + "Required key text is present", + f"The slide must preserve the exact key text `{spec.key_text}` as editable text.", + "text", + "critical", + "ooxml", + verification("text_match", "slide_text", {"contains": spec.key_text}), + ), + item( + number, + "native-primary", + "Primary native construct is present", + f"The primary structural requirement is {spec.primary_description}; raster or shape imitations do not qualify.", + spec.primary_kind, + "critical", + "ooxml", + primary_check, + ), + item( + number, + "layout-binding", + f"{spec.layout} layout binding", + f"The slide must be bound to the `{spec.layout}` master layout and use its required inherited content.", + "master-layout", + "critical", + "ooxml", + layout_check, + ), + item( + number, + "font-policy", + "Bundled font policy", + "Every rendered text run must use a bundled Liberation, Carlito, Caladea, or Noto family.", + "typography", + "critical", + "ooxml", + verification("anti_cheat", "font_policy"), + { + "automatic_fail_if": ["non_bundled_font_used"], + "propagation": "zero_slide", + }, + ), + item( + number, + "composition", + "Required composition inventory", + f"The slide composition must include {spec.composition}.", + "structure", + "major", + "both", + verification( + "object_compare", + spec.composition_selector, + {"min_count": spec.composition_count}, + ), + ), + item( + number, + "full-slide-fidelity", + "Full-slide rendered fidelity", + "The complete 1920×1080 LibreOffice export must meet the v1 SSIM threshold against the gold export.", + "visual", + "major", + "render", + verification("visual_ssim", "full_slide", {"min_ssim": 0.9999}), + ), + item( + number, + "focal-fidelity", + "Focal region rendered fidelity", + f"The full-slide SSIM gate must preserve the appearance of {spec.focal_region}; this label identifies the diagnostic focal region.", + "visual", + "major", + "render", + verification( + "visual_ssim", + "full_slide", + {"min_ssim": 0.9999, "diagnostic_region": spec.focal_region}, + ), + ), + item( + number, + "hierarchy-z-order", + "Hierarchy and z-order semantics", + f"Preserve {spec.hierarchy} in native OOXML and in the rendered result.", + "z-order", + "major", + "both", + verification( + "object_compare", + spec.composition_selector, + {"min_count": spec.composition_count}, + ), + ), + item( + number, + "semantic-structure", + "Semantic structure matches prompt", + f"The editable object graph must express {spec.primary_description} while remaining visually equivalent to the reference.", + spec.primary_kind, + "major", + "both", + verification( + "object_compare", + spec.primary_selector, + {"min_count": spec.primary_count}, + ), + ), + item( + number, + "palette", + "Palette fidelity", + "The rendered slide must use the exact deck palette values in the regions specified by the prompt.", + "visual", + "minor", + "render", + verification( + "visual_ssim", + "full_slide", + {"min_ssim": 0.9999, "diagnostic": "palette"}, + ), + ), + item( + number, + "typography", + "Typography fidelity", + "Font family, size, weight, line breaking, and visible text color must match in the full-slide export.", + "typography", + "minor", + "render", + verification( + "visual_ssim", + "full_slide", + {"min_ssim": 0.9999, "diagnostic": "typography"}, + ), + ), + item( + number, + "spacing", + "Geometry and spacing fidelity", + "Object bounds, alignment, padding, and spacing must match the specified geometry and the reference export.", + "spacing-autofit", + "minor", + "both", + verification( + "visual_ssim", + "full_slide", + {"min_ssim": 0.9999, "diagnostic": "geometry"}, + ), + ), + item( + number, + "decorative-detail", + "Decorative and effect details", + f"Preserve {spec.decorative_detail} as editable native detail.", + "gradient-pattern", + "minor", + "ooxml", + verification( + "object_compare", + spec.composition_selector, + {"min_count": spec.composition_count}, + ), + ), + ] + + +def deck_item( + suffix: str, + tier: int, + title: str, + description: str, + kind: str, + severity: str, + source: str, + check: dict, + failure_mode: dict | None = None, +) -> dict: + result = { + "schema_version": "1.0", + "id": f"deck.{suffix}", + "scope": "deck", + "tier": tier, + "title": title, + "description": description, + "kind": kind, + "severity": severity, + "source_of_truth": source, + "verification": check, + } + if failure_mode: + failure_mode = dict(failure_mode) + failure_mode.setdefault( + "affected_slides", + { + "status": "pending", + "reason": "The content-addressed deck-level affected-slide selector and evidence are not frozen.", + }, + ) + result["failure_mode"] = failure_mode + result.update(pending_checklist_metadata(result["id"])) + return result + + +def named_affected_slides(selector_id: str) -> dict: + """Resolve one content-addressed selector binding from the candidate registry.""" + registry_path = BENCHMARK / "requirements" / "affected-slide-selectors-v1.json" + registry = json.loads(registry_path.read_text(encoding="utf-8")) + matches = [entry for entry in registry["selectors"] if entry["selector_id"] == selector_id] + if len(matches) != 1: + raise ValueError(f"Expected one affected-slide selector {selector_id!r}") + return { + "status": "complete", + "mode": "named_selector", + "slides": [], + "selector_id": selector_id, + "selector_sha256": matches[0]["selector_sha256"], + } + + +def deck_items(asset_hashes: dict[str, str]) -> list[dict]: + return [ + deck_item( + "slide-count", + 1, + "Exactly 20 slides", + "The Level 3 deck contains exactly 20 ordered slides.", + "structure", + "critical", + "ooxml", + verification("object_compare", "slide_count", {"exact_count": 20}), + ), + deck_item( + "master-present", + 1, + "AcidSlide master exists", + "At least one native slide master must own the shared background and footer elements.", + "master-layout", + "critical", + "ooxml", + verification("layout_check", "master_count", {"min_count": 1}), + ), + deck_item( + "font-policy", + 1, + "Only bundled fonts render", + "All rendered text uses the bundled font inventory.", + "typography", + "critical", + "ooxml", + verification("anti_cheat", "font_policy"), + { + "automatic_fail_if": ["non_bundled_font_used"], + "propagation": "zero_affected_slides", + "affected_slides": named_affected_slides( + "acidslide.affected-slides.non-bundled-font.v1" + ), + }, + ), + deck_item( + "no-notes", + 1, + "No notes or comments", + "The package contains no speaker notes or comments.", + "structure", + "critical", + "ooxml", + verification("anti_cheat", "no_notes"), + { + "automatic_fail_if": ["notes_or_comments_present"], + "propagation": "zero_affected_slides", + "affected_slides": named_affected_slides( + "acidslide.affected-slides.notes-comments.v1" + ), + }, + ), + deck_item( + "layouts-defined", + 1, + "Four canonical layouts", + "Title Slide, Content Slide, Two-Column, and Blank with Footer layouts are defined.", + "master-layout", + "major", + "ooxml", + verification("layout_check", "layout_count", {"min_count": 4}), + ), + deck_item( + "approved-assets", + 1, + "Approved media inventory", + "Every required benchmark asset hash occurs in embedded media and no unapproved external media is introduced.", + "image-asset", + "major", + "ooxml", + verification("hash_match", "asset_manifest", {"asset_hashes": asset_hashes}), + ), + deck_item( + "native-slide-numbers", + 1, + "Slide numbers are inherited fields", + "Slide numbers originate in the master/layout field rather than copied local text.", + "fields", + "major", + "ooxml", + verification("layout_check", "master_count", {"min_count": 1}), + ), + deck_item( + "ordered-tier-prefix", + 1, + "Tier slide order is stable", + "Level 1 and Level 2 remain ordered prefixes of the 20-slide Level 3 deck.", + "structure", + "major", + "ooxml", + verification("object_compare", "slide_count", {"exact_count": 20}), + ), + deck_item( + "theme-structure", + 2, + "Theme references remain semantic", + "Theme-driven colors and local overrides remain distinct in OOXML across the deck.", + "theme-consistency", + "major", + "ooxml", + verification("layout_check", "master_count", {"min_count": 1}), + ), + deck_item( + "native-object-coverage", + 2, + "Native construct coverage", + "The deck contains native charts, tables, fields, connectors, groups, placeholders, and pictures where prompted.", + "structure", + "major", + "ooxml", + verification("object_compare", "slide_count", {"exact_count": 20}), + ), + deck_item( + "rtl-cjk-coverage", + 2, + "RTL and CJK coverage", + "Arabic RTL and Japanese CJK content remain editable and correctly encoded.", + "multilingual", + "major", + "ooxml", + verification("object_compare", "slide_count", {"exact_count": 20}), + ), + deck_item( + "render-consistency", + 1, + "Deck-wide render consistency", + "All slide exports pass the official SSIM threshold against their corresponding gold exports.", + "visual", + "major", + "render", + verification("visual_ssim", "all_slides", {"min_ssim": 0.9999}), + ), + deck_item( + "master-visual-consistency", + 1, + "Inherited footer renders consistently", + "The shared footer line, company label, and slide number align identically across applicable slides.", + "theme-consistency", + "major", + "render", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "footer"}, + ), + ), + deck_item( + "palette-consistency", + 1, + "Deck palette is coherent", + "Repeated palette roles render consistently across all 20 slides.", + "theme-consistency", + "major", + "render", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "palette"}, + ), + ), + deck_item( + "typography-consistency", + 1, + "Deck typography is coherent", + "Repeated type roles render with the same family, size, weight, and color throughout the deck.", + "typography", + "major", + "render", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "typography"}, + ), + ), + deck_item( + "spacing-consistency", + 2, + "Deck spacing is coherent", + "Repeated margins, gutters, and title anchors align across slide layouts.", + "spacing-autofit", + "major", + "render", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "spacing"}, + ), + ), + deck_item( + "cross-slide-hierarchy", + 3, + "Cross-slide hierarchy matches", + "Title, body, focal, and footer hierarchy remains structurally and visually consistent.", + "theme-consistency", + "minor", + "both", + verification("layout_check", "master_count", {"min_count": 1}), + ), + deck_item( + "line-weight-detail", + 3, + "Repeated line weights match", + "Master rules, separators, borders, and connectors use the specified weights.", + "visual", + "minor", + "both", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "line_weights"}, + ), + ), + deck_item( + "effect-detail", + 3, + "Repeated effects match", + "Shadows, transparency, gradients, and patterns render consistently where repeated.", + "gradient-pattern", + "minor", + "both", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "effects"}, + ), + ), + deck_item( + "alignment-detail", + 3, + "Repeated alignment anchors match", + "Common title, footer, and grid anchors remain aligned throughout the deck.", + "spacing-autofit", + "minor", + "both", + verification( + "visual_ssim", + "all_slides", + {"min_ssim": 0.9999, "diagnostic": "alignment"}, + ), + ), + ] + + +def write_yaml_documents(path: Path, documents: list[dict]) -> None: + path.write_text( + "\n---\n".join(json.dumps(doc, ensure_ascii=False, indent=2) for doc in documents) + "\n", + encoding="utf-8", + ) + + +def write_checklist(asset_hashes: dict[str, str]) -> list[dict]: + documents = deck_items(asset_hashes) + write_yaml_documents(BENCHMARK / "checklist" / "deck.yaml", documents) + slides_dir = BENCHMARK / "checklist" / "slides" + for number in range(1, 21): + slide_documents = slide_items(number, asset_hashes) + write_yaml_documents(slides_dir / f"slide-{number:02d}.yaml", slide_documents) + documents.extend(slide_documents) + return documents + + +def _assertion_property_class(item: dict) -> str: + kind = item["kind"] + if kind == "master-layout": + return "master" if "master" in item["id"] else "layout" + return { + "structure": "native_structure", + "typography": "visual_typography", + "image-asset": "asset_identity", + "fields": "field", + "theme-consistency": "theme", + "multilingual": "text_content", + "visual": "visual_appearance", + "spacing-autofit": "visual_spacing", + "gradient-pattern": "visual_color", + "text": "text_content", + "z-order": "native_structure", + "grouping": "native_structure", + "table": "table", + "chart": "chart", + "overflow": "editability", + }[kind] + + +def write_scored_assertion_candidate(documents: list[dict]) -> None: + """Write reviewable candidate assertions without inventing provenance or evidence.""" + + pending_provenance = ( + "Atomic prompt/reference/asset provenance has not yet been independently reviewed." + ) + pending_evidence = ( + "Positive, single-fault negative, and mutation evidence has not yet been observed." + ) + assertions: list[dict] = [] + for item_document in documents: + verification = item_document["verification"] + expected = dict(verification.get("expectation", {})) + if selector := verification.get("selector"): + expected["selector"] = selector + if not expected: + expected["rule"] = item_document["id"] + method = verification["method"] + if method == "hash_match": + method = "embedded_media_hash" + assertions.append( + { + "schema_version": "1.0", + "lifecycle_state": "candidate", + "assertion_id": item_document["assertion_id"], + "checklist_item_id": item_document["id"], + "scope": item_document["scope"], + **({"slide": item_document["slide"]} if item_document["scope"] == "slide" else {}), + "tier": item_document["tier"], + "statement": item_document["description"], + "provenance": {"status": "pending", "reason": pending_provenance}, + "property_class": _assertion_property_class(item_document), + "source_of_truth": item_document["source_of_truth"], + "verification_method": method, + "expected_observation": expected, + "evidence": {"status": "pending", "reason": pending_evidence}, + "gold_ooxml_is_oracle": False, + } + ) + inventory = { + "schema_version": "1.0", + "inventory_id": "acidslide-scored-assertion-inventory-v1", + "lifecycle_state": "candidate", + "benchmark_version": "acidslide-v1.0.0", + "prompt_bundle_sha256": "pending", + "reference_image_bundle_sha256": "pending", + "asset_manifest_sha256": f"sha256:{sha256(BENCHMARK / 'assets' / 'manifest.json')}", + "review": { + "status": "pending", + "reason": "Assertion provenance and fixture evidence are not independently approved.", + }, + "assertions": assertions, + } + destination = BENCHMARK / "requirements" / "scored-assertion-inventory.json" + destination.write_text(json.dumps(inventory, ensure_ascii=False, indent=2) + "\n") + + +PACKAGES = { + "Liberation": { + "package": "fonts-liberation", + "version": "1:1.07.4-11", + "license": "GPL-2.0-with-font-exception", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-liberation/fonts-liberation_1.07.4-11_all.deb", + "package_sha256": "d359cba9c3ac8a40fb57773881e20827845e9fab1b2d6fd25cde4b7bade7d57f", + "license_file": "licenses/fonts-liberation-1.07.4-11.txt", + }, + "Carlito": { + "package": "fonts-crosextra-carlito", + "version": "20130920-1.1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/universe/f/fonts-crosextra-carlito/fonts-crosextra-carlito_20130920-1.1_all.deb", + "package_sha256": "7385475cde807e1363c3361976576571870373032466c7f525d5900852b6f420", + "license_file": "licenses/fonts-crosextra-carlito-20130920-1.1.txt", + }, + "Caladea": { + "package": "fonts-crosextra-caladea", + "version": "20130214-2.1", + "license": "Apache-2.0", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/universe/f/fonts-crosextra-caladea/fonts-crosextra-caladea_20130214-2.1_all.deb", + "package_sha256": "1330d25dfa5bab2e9b712b4950d2855cdb63a2b2b9451e2ffb93618c77e1f242", + "license_file": "licenses/fonts-crosextra-caladea-20130214-2.1.txt", + }, + "Noto Sans CJK": { + "package": "fonts-noto-cjk", + "version": "1:20220127+repack1-1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-noto-cjk/fonts-noto-cjk_20220127+repack1-1_all.deb", + "package_sha256": "e804b3474a79bd70d5f03f590e2d06dbc5ce17f48be7cfaf6c48086471edd5be", + "license_file": "licenses/fonts-noto-cjk-20220127+repack1-1.txt", + }, + "Noto Sans": { + "package": "fonts-noto-core", + "version": "20201225-1build1", + "license": "OFL-1.1", + "source_url": "https://archive.ubuntu.com/ubuntu/pool/main/f/fonts-noto/fonts-noto-core_20201225-1build1_all.deb", + "package_sha256": "653d237d5c4e8fcebb2710129ebbd7bf9bc248d03dfff23fcf261b0372fded69", + "license_file": "licenses/fonts-noto-core-20201225-1build1.txt", + }, +} + + +def font_family(filename: str) -> str: + if filename.startswith("Liberation"): + return filename.split("-")[0].replace("Liberation", "Liberation ") + if filename.startswith("NotoSansCJK"): + return "Noto Sans CJK JP" + if filename.startswith("NotoSansArabic"): + return "Noto Sans Arabic" + if filename.startswith("NotoSans"): + return "Noto Sans" + return filename.split("-")[0] + + +def package_for(filename: str) -> str: + if filename.startswith("Liberation"): + return "Liberation" + if filename.startswith("Carlito"): + return "Carlito" + if filename.startswith("Caladea"): + return "Caladea" + if filename.startswith("NotoSansCJK"): + return "Noto Sans CJK" + return "Noto Sans" + + +def write_manifests() -> dict[str, str]: + assets = [ + ("hero-abstract", "hero-abstract.png", ["slide-01", "slide-20"], [1920, 1080]), + ( + "cityscape", + "cityscape.png", + ["slide-07", "slide-13", "slide-18"], + [2400, 1600], + ), + ( + "texture-pattern", + "texture-pattern.png", + ["slide-07", "slide-18"], + [800, 800], + ), + ] + entries = [] + asset_hashes = {} + for asset_id, filename, usage, dimensions in assets: + local = BENCHMARK / "assets" / "mirrored" / filename + source = BENCHMARK / "assets" / "sources" / filename.replace(".png", ".svg") + digest = sha256(local) + asset_hashes[asset_id] = digest + entries.append( + { + "asset_id": asset_id, + "filename": filename, + "media_type": "image/png", + "dimensions_px": dimensions, + "source_url": None, + "source_path": f"sources/{source.name}", + "source_sha256": sha256(source), + "local_path": f"mirrored/{filename}", + "sha256": digest, + "accepted_recompression_hashes": [], + "recompression_status": "pending_gold_deck_extraction", + "usage": usage, + "license": "CC0-1.0", + "license_file": "LICENSE", + "attribution": "AcidSlide benchmark maintainers", + "provenance": "hand-authored procedural SVG rendered locally with librsvg; no third-party or model-generated content", + } + ) + asset_manifest = { + "schema_version": "1.0", + "policy": "allowlist-only", + "assets": entries, + } + (BENCHMARK / "assets" / "manifest.json").write_text( + json.dumps(asset_manifest, indent=2) + "\n", encoding="utf-8" + ) + + files = [] + for path in sorted((BENCHMARK / "fonts" / "files").iterdir()): + if path.suffix.lower() not in {".ttf", ".ttc", ".otf"}: + continue + package_key = package_for(path.name) + package = PACKAGES[package_key] + style = path.stem.split("-", 1)[1] if "-" in path.stem else "Regular" + files.append( + { + "family": font_family(path.name), + "style": style, + "local_path": f"files/{path.name}", + "sha256": sha256(path), + "package": package["package"], + "package_version": package["version"], + "license": package["license"], + "license_file": package["license_file"], + } + ) + font_manifest = { + "schema_version": "1.0", + "runtime": "Ubuntu 22.04 (jammy)", + "policy": "only listed font files may be used in rendered text", + "packages": list(PACKAGES.values()), + "files": files, + } + (BENCHMARK / "fonts" / "manifest.json").write_text( + json.dumps(font_manifest, indent=2) + "\n", encoding="utf-8" + ) + return asset_hashes + + +def main() -> None: + asset_hashes = write_manifests() + write_prompts() + documents = write_checklist(asset_hashes) + write_scored_assertion_candidate(documents) + print( + "built prompts, validation records, manifests, 280 checklist items, " + "and candidate scored assertions" + ) + + +if __name__ == "__main__": + main() diff --git a/acidslide-v1/benchmark/tools/build_mutation_fixtures.py b/acidslide-v1/benchmark/tools/build_mutation_fixtures.py new file mode 100644 index 0000000..4371d5f --- /dev/null +++ b/acidslide-v1/benchmark/tools/build_mutation_fixtures.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Generate and execute the candidate operator-level mutation fixture matrix.""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path +from typing import Any + +ACIDSLIDE_ROOT = Path(__file__).resolve().parents[2] +BENCHMARK = ACIDSLIDE_ROOT / "benchmark" +GRADER = ACIDSLIDE_ROOT / "grader" +sys.path.insert(0, str(GRADER)) + +from acidslide.checklist import load_checklist # noqa: E402 +from acidslide.mutation_fixtures import ( # noqa: E402 + build_fixture_index, + build_mutation_expectations, + execute_fixture_matrix, +) + + +def _documents() -> dict[str, dict[str, Any]]: + items = load_checklist(BENCHMARK / "checklist", tier=3) + inventory = json.loads( + (BENCHMARK / "requirements" / "scored-assertion-inventory.json").read_text(encoding="utf-8") + ) + fixture_index = build_fixture_index(items, inventory) + expectations = build_mutation_expectations(fixture_index) + execution = execute_fixture_matrix(items, fixture_index) + return { + "fixture-index-v1.json": fixture_index, + "mutation-expectations-v1.json": expectations, + "execution-report-v1.json": execution, + } + + +def _encoded(document: dict[str, Any]) -> str: + return json.dumps(document, ensure_ascii=False, indent=2, sort_keys=True) + "\n" + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--output-dir", + type=Path, + default=BENCHMARK / "fixtures" / "mutations", + ) + parser.add_argument( + "--check", + action="store_true", + help="Fail if checked-in generated documents are absent or stale.", + ) + args = parser.parse_args() + + documents = _documents() + if args.check: + stale = [ + name + for name, document in documents.items() + if not (args.output_dir / name).is_file() + or (args.output_dir / name).read_text(encoding="utf-8") != _encoded(document) + ] + if stale: + raise SystemExit(f"Generated mutation documents are stale: {', '.join(stale)}") + else: + args.output_dir.mkdir(parents=True, exist_ok=True) + for name, document in documents.items(): + (args.output_dir / name).write_text(_encoded(document), encoding="utf-8") + + summary = documents["execution-report-v1.json"]["summary"] + print( + "AcidSlide mutation fixtures: " + f"{summary['killed_mutants']}/{summary['executed_single_fault_negative_fixtures']} " + "mutants killed; " + f"{summary['unimplemented_items']} unimplemented; " + "0 release-evidence claims" + ) + + +if __name__ == "__main__": + main() diff --git a/acidslide-v1/benchmark/tools/build_prompt_requirements.py b/acidslide-v1/benchmark/tools/build_prompt_requirements.py new file mode 100644 index 0000000..7c193c4 --- /dev/null +++ b/acidslide-v1/benchmark/tools/build_prompt_requirements.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python3 +"""Build the traceable candidate prompt-requirements inventory. + +The output is intentionally not marked frozen: line-level extraction is a +starting inventory for the two independent reviewers, not a substitute for +their atomicity/completeness review or the required fixture/mutation evidence. +""" + +from __future__ import annotations + +import hashlib +import json +import re +from pathlib import Path +from typing import Any + +import jsonschema + +ROOT = Path(__file__).resolve().parents[2] +BENCHMARK = ROOT / "benchmark" +PROMPTS = BENCHMARK / "prompts" +OUTPUT = BENCHMARK / "requirements" / "prompt-requirements.json" +SCHEMA = ROOT / "schemas" / "prompt-requirements.schema.json" +LIST_PREFIX = re.compile(r"^\s*(?:\d+\.|[-*])\s+(.*)$") +TABLE_DIVIDER = re.compile(r"^\|(?:\s*:?-+:?\s*\|)+$") +CONTEXT_LABEL = re.compile(r"^\s*(?:\d+\.\s+)?\*\*(.+?):?\*\*:?\s*$") +CONTENT_BEARING_DECK_HEADINGS = frozenset( + { + '#### Master: "AcidSlide Master"', + '#### Layout 1: "Title Slide"', + '#### Layout 2: "Content Slide"', + '#### Layout 3: "Two-Column"', + '#### Layout 4: "Blank with Footer"', + } +) +CONTENT_BEARING_TABLE_HEADERS = { + "benchmark/prompts/variants/canonical/slide-03.md": ( + "| Metric | Q1 2024 | Q2 2024 | Q3 2024 | Target |" + ), + "benchmark/prompts/variants/canonical/slide-04.md": ( + "| Region | 2023 Revenue ($M) | 2024 Revenue ($M) |" + ), +} + + +def _sha256(data: bytes) -> str: + return hashlib.sha256(data).hexdigest() + + +def _source(path: Path, source_id: str) -> dict[str, Any]: + return { + "source_id": source_id, + "source_type": "prompt", + "authority": "primary", + "path": path.relative_to(ROOT).as_posix(), + "sha256": _sha256(path.read_bytes()), + } + + +def _units(path: Path, *, deck: bool) -> list[tuple[int, int, str, str]]: + """Return every directive clause, including adjudicated content-bearing labels. + + Unitization is intentionally source-shaped and deterministic: + + - fenced examples and wrapped prose paragraphs are inclusive multi-line units; + - list items and table data rows are individual units; + - the five named master/layout headings and Slide 3/4 native-data headers are + requirements because their text is content, not merely Markdown context; + - all other table headers, dividers, section headings, and numbered subsection + labels provide context only and are never standalone requirements. + """ + + lines = path.read_text(encoding="utf-8").splitlines() + units: list[tuple[int, int, str, str]] = [] + context: str | None = None + index = 0 + + while index < len(lines): + raw = lines[index] + stripped = raw.strip() + line_number = index + 1 + + if not deck and stripped.startswith("**Why this slide is hard"): + break + if not stripped or stripped == "---": + index += 1 + continue + if stripped.startswith("#"): + if deck and stripped in CONTENT_BEARING_DECK_HEADINGS: + statement = stripped.lstrip("#").strip() + units.append((line_number, line_number, raw, statement)) + index += 1 + continue + if stripped.startswith("The natural-language requirements below"): + index += 1 + continue + if stripped.startswith("**Tier:") or stripped == "**What to build:**": + index += 1 + continue + + label = CONTEXT_LABEL.fullmatch(raw) + if label: + context = label.group(1).strip() + index += 1 + continue + + if stripped.startswith("```"): + end = index + 1 + while end < len(lines) and not lines[end].strip().startswith("```"): + end += 1 + if end >= len(lines): + raise RuntimeError(f"unterminated fenced block in {path}:{line_number}") + excerpt = "\n".join(lines[index : end + 1]) + literal = "\n".join(lines[index + 1 : end]).strip("\n") + statement = "Use this fenced prompt content as directed" + if context: + statement += f" for {context}" + statement += f":\n{literal}" + units.append((line_number, end + 1, excerpt, statement)) + index = end + 1 + continue + + if stripped.startswith("|") and stripped.endswith("|"): + if index + 1 < len(lines) and TABLE_DIVIDER.fullmatch( + lines[index + 1].strip().replace(" ", "") + ): + source_path = path.relative_to(ROOT).as_posix() + if CONTENT_BEARING_TABLE_HEADERS.get(source_path) == stripped: + units.append( + ( + line_number, + line_number, + raw, + f"Use this exact table header row: {stripped}", + ) + ) + # Keep the header as context for the data rows and skip the + # divider as syntax, whether or not it is also content-bearing. + context = " / ".join(cell.strip() for cell in stripped.strip("|").split("|")) + index += 2 + continue + if TABLE_DIVIDER.fullmatch(stripped.replace(" ", "")): + index += 1 + continue + statement = f"Use this exact table data row: {stripped}" + if context: + statement = f"{context}: {statement}" + units.append((line_number, line_number, raw, statement)) + index += 1 + continue + + list_match = LIST_PREFIX.match(raw) + if list_match: + statement = _strip_markdown(list_match.group(1).strip()) + if context and raw.startswith((" -", " *", " -", " *")): + statement = f"{context}: {statement}" + units.append((line_number, line_number, raw, statement)) + inline_label = re.match(r"^\*\*(.+?)\*\*:?", list_match.group(1).strip()) + if inline_label: + context = inline_label.group(1).rstrip(":").strip() + index += 1 + continue + + # A prose paragraph is one source clause, even when line-wrapped. + end = index + while end + 1 < len(lines): + following = lines[end + 1] + following_stripped = following.strip() + if ( + not following_stripped + or following_stripped == "---" + or following_stripped.startswith(("#", "```", "|")) + or following_stripped.startswith("**Tier:") + or following_stripped == "**What to build:**" + or LIST_PREFIX.match(following) + or CONTEXT_LABEL.fullmatch(following) + ): + break + end += 1 + excerpt = "\n".join(lines[index : end + 1]) + units.append((line_number, end + 1, excerpt, _strip_markdown(excerpt))) + index = end + 1 + + return units + + +def _strip_markdown(value: str) -> str: + value = re.sub(r"^\*\*[^*]+\*\*:\s*", "", value) + value = value.replace("**", "") + return value.strip() + + +def _requirement( + *, + source_id: str, + scope: str, + sequence: int, + line_start: int, + line_end: int, + excerpt: str, + statement: str, + slide: int | None, +) -> dict[str, Any]: + lower = statement.lower() + exact_tokens = ("`", "exact", "text", "font", "#", "cm", "pt", "%", "°", "|") + mode = "exact" if any(token in statement for token in exact_tokens) else "structural_semantic" + structural_tokens = ( + "native", + "placeholder", + "layout", + "master", + "group", + "field", + "rtl", + "hyperlink", + "editable", + "ooxml", + "inherit", + ) + visual_tokens = ( + "position", + "size", + "fill", + "color", + "spacing", + "align", + "crop", + "shadow", + "opacity", + "overlap", + "z-order", + "border", + "gradient", + ) + structural = any(token in lower for token in structural_tokens) + visual = any(token in lower for token in visual_tokens) + source_of_truth = "both" if structural and visual else "ooxml" if structural else "both" + severity = ( + "critical" + if any(token in statement for token in ("MUST", "CRITICAL", "ONLY", "Do NOT", "NO ")) + or "native" in lower + else "major" + ) + prefix = "deck" if scope == "deck" else f"slide-{slide:02d}" + result: dict[str, Any] = { + "requirement_id": f"{prefix}.prompt-r{sequence:03d}", + "scope": scope, + "mandatory": True, + "statement": statement, + "provenance": { + "source_id": source_id, + "source_type": "prompt", + "line_start": line_start, + "line_end": line_end, + "excerpt": excerpt, + "excerpt_sha256": _sha256(excerpt.encode("utf-8")), + }, + "severity": severity, + "source_of_truth": source_of_truth, + "matching_policy": { + "mode": mode, + "normalization": ( + "Exact Unicode, numeric values, units, and named OOXML construct after only " + "prompt-declared unit conversion." + if mode == "exact" + else "Match every named visible and structural property; do not infer from gold." + ), + }, + "equivalence_policy": { + "allowed": [ + "Alternative native OOXML serialization preserving every property named by " + "this clause." + ], + "forbidden": [ + "Gold-derived expectations, raster substitutes, or omission of a property named " + "by this clause." + ], + }, + "assertion": { + "operator": "satisfies_prompt_clause", + "expected_clause": statement, + "automation_status": "unimplemented", + }, + "fixture_expectations": { + "positive_fixture_ids": [], + "single_fault_negative_fixture_ids": [], + "mutation_ids": [], + }, + "review_status": "pending", + } + if slide is not None: + result["slide"] = slide + return result + + +def build() -> dict[str, Any]: + deck_path = PROMPTS / "deck.md" + slide_paths = [ + PROMPTS / "variants" / "canonical" / f"slide-{number:02d}.md" for number in range(1, 21) + ] + sources = [_source(deck_path, "deck-prompt")] + sources.extend( + _source(path, f"slide-{number:02d}-prompt") for number, path in enumerate(slide_paths, 1) + ) + requirements: list[dict[str, Any]] = [] + for sequence, unit in enumerate(_units(deck_path, deck=True), 1): + requirements.append( + _requirement( + source_id="deck-prompt", + scope="deck", + sequence=sequence, + line_start=unit[0], + line_end=unit[1], + excerpt=unit[2], + statement=unit[3], + slide=None, + ) + ) + for slide, path in enumerate(slide_paths, 1): + for sequence, unit in enumerate(_units(path, deck=False), 1): + requirements.append( + _requirement( + source_id=f"slide-{slide:02d}-prompt", + scope="slide", + sequence=sequence, + line_start=unit[0], + line_end=unit[1], + excerpt=unit[2], + statement=unit[3], + slide=slide, + ) + ) + return { + "schema_version": "1.0", + "oracle_id": "acidslide-prompt-requirements-v1", + "benchmark_version": "acidslide-v1.0.0", + "freeze_status": "candidate_pending_independent_review", + "sources": sources, + "independent_reviews": [], + "requirements": requirements, + } + + +def main() -> None: + document = build() + schema = json.loads(SCHEMA.read_text(encoding="utf-8")) + jsonschema.Draft202012Validator(schema).validate(document) + OUTPUT.parent.mkdir(parents=True, exist_ok=True) + OUTPUT.write_text(json.dumps(document, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") + counts = { + scope: sum(1 for item in document["requirements"] if item["scope"] == scope) + for scope in ("deck", "slide") + } + print(f"wrote {OUTPUT}: {counts['deck']} deck + {counts['slide']} slide requirements") + + +if __name__ == "__main__": + main() diff --git a/acidslide-v1/benchmark/tools/build_scoring_manifest.py b/acidslide-v1/benchmark/tools/build_scoring_manifest.py new file mode 100644 index 0000000..abeac5b --- /dev/null +++ b/acidslide-v1/benchmark/tools/build_scoring_manifest.py @@ -0,0 +1,392 @@ +#!/usr/bin/env python3 +# ruff: noqa: E402 +"""Build a frozen AcidSlide v1 scoring manifest or fail without writing one. + +This command intentionally has no draft/placeholder mode. A manifest is a +release identity, so absent gold, exports, OCI identity, runtime attestation, +or grader package is an error rather than a field containing ``pending``. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import sys +from pathlib import Path +from typing import Any + +import jsonschema +import rfc8785 +from referencing import Registry, Resource + +ROOT = Path(__file__).resolve().parents[2] +GRADER = ROOT / "grader" +sys.path.insert(0, str(GRADER)) + +from acidslide.package_hash import canonical_package_sha256, sha256_file +from acidslide.profile_contract import ( + deterministic_tree_sha256, + environment_profile_hashes, + load_render_profiles, +) +from acidslide.release_evidence import validate_export_determinism_evidence + + +def _arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--runtime", type=Path, required=True, help="validated runtime freeze JSON") + parser.add_argument( + "--gold", + type=Path, + default=ROOT / "benchmark" / "deck" / "gold" / "acidslide-v1-gold.pptx", + ) + parser.add_argument( + "--gold-exports", + type=Path, + default=ROOT / "benchmark" / "deck" / "exports", + ) + parser.add_argument( + "--resolved-gold", + type=Path, + required=True, + help="content-addressed Stage-0.5 MCE-resolved gold package", + ) + parser.add_argument( + "--gold-pdf", + type=Path, + required=True, + help="canonical 20-page PDF retained from the frozen export run", + ) + parser.add_argument( + "--environment-attestation", + type=Path, + required=True, + help="validated environment-attestation JSON reconstructed in the container", + ) + parser.add_argument( + "--export-determinism-evidence", + type=Path, + required=True, + help="validated 100-run gold export determinism evidence", + ) + parser.add_argument( + "--grader-source-tree-manifest", + type=Path, + required=True, + help="validated complete grader source-tree manifest", + ) + parser.add_argument("--grader-package", type=Path, required=True, help="release wheel or sdist") + parser.add_argument("--output", type=Path, required=True) + return parser.parse_args() + + +def _sha256(path: Path) -> str: + if not path.is_file(): + raise FileNotFoundError(f"Required release artifact is missing: {path}") + return f"sha256:{sha256_file(path)}" + + +def _tree_sha256(path: Path) -> str: + return deterministic_tree_sha256(path) + + +def _load_validated(path: Path, schema_path: Path) -> dict[str, Any]: + document: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) + schema = json.loads(schema_path.read_text(encoding="utf-8")) + registry = Registry() + for candidate in sorted((ROOT / "schemas").glob("*.schema.json")): + candidate_schema = json.loads(candidate.read_text(encoding="utf-8")) + identifier = candidate_schema.get("$id") + if isinstance(identifier, str): + registry = registry.with_resource(identifier, Resource.from_contents(candidate_schema)) + jsonschema.Draft202012Validator( + schema, + registry=registry, + format_checker=jsonschema.FormatChecker(), + ).validate(document) + return document + + +def _jcs_sha256(document: dict[str, Any]) -> str: + return f"sha256:{hashlib.sha256(rfc8785.dumps(document)).hexdigest()}" + + +class _EvidenceValidationResult: + def __init__(self) -> None: + self.errors: list[str] = [] + self.notes: list[str] = [] + + def require(self, condition: bool, message: str) -> None: + if not condition: + self.errors.append(message) + + +def build_manifest( + *, + runtime_path: Path, + gold_path: Path, + gold_exports: Path, + resolved_gold: Path, + gold_pdf: Path, + environment_attestation_path: Path, + export_determinism_evidence_path: Path, + grader_source_tree_manifest_path: Path, + grader_package: Path, +) -> dict[str, Any]: + """Return a fully resolved manifest; raise on any missing release input.""" + version = (ROOT / "VERSION").read_text(encoding="utf-8").strip() + if version != "1.0.0": + raise ValueError(f"VERSION must be exactly 1.0.0 for the v1 freeze, found {version!r}") + runtime = _load_validated( + runtime_path, + ROOT / "schemas" / "runtime-freeze-input.schema.json", + ) + environment_attestation = _load_validated( + environment_attestation_path, + ROOT / "schemas" / "environment-attestation.schema.json", + ) + environment_attestation_sha256 = _jcs_sha256(environment_attestation) + if environment_attestation_sha256 != runtime["environment_attestation_sha256"]: + raise ValueError( + "Runtime freeze environment_attestation_sha256 does not match the JCS attestation" + ) + if runtime["platform"] != environment_attestation["platform"]: + raise ValueError("Runtime freeze platform does not match the environment attestation") + if runtime["oci_image_digest"] != environment_attestation["oci_image_digest"]: + raise ValueError("Runtime freeze OCI digest does not match the environment attestation") + runtime_versions = environment_attestation["runtime_versions"] + for field in ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + ): + if runtime[field] != runtime_versions[field]: + raise ValueError(f"Runtime freeze {field} does not match the environment attestation") + if ( + runtime["fontconfig_config_sha256"] + != environment_attestation["font_environment"]["fontconfig_config_sha256"] + ): + raise ValueError( + "Runtime freeze Fontconfig hash does not match the environment attestation" + ) + libfaketime_records = [ + record + for record in environment_attestation["binary_inventory"] + if record["name"] == "libfaketime" + ] + if ( + len(libfaketime_records) != 1 + or runtime["libfaketime_library_sha256"] != libfaketime_records[0]["sha256"] + ): + raise ValueError( + "Runtime freeze libfaketime library hash does not match the environment attestation" + ) + determinism_evidence = _load_validated( + export_determinism_evidence_path, + ROOT / "schemas" / "export-determinism-evidence.schema.json", + ) + source_tree_manifest = _load_validated( + grader_source_tree_manifest_path, + ROOT / "schemas" / "grader-source-tree-manifest.schema.json", + ) + source_tree_sha256 = _jcs_sha256(source_tree_manifest) + exports = sorted(gold_exports.glob("slide-??.png")) + if len(exports) != 20 or [path.name for path in exports] != [ + f"slide-{number:02d}.png" for number in range(1, 21) + ]: + raise ValueError("Gold export tree must contain exactly slide-01.png through slide-20.png") + + schemas = ROOT / "schemas" + benchmark = ROOT / "benchmark" + oracle = benchmark / "requirements" / "prompt-requirements.json" + scored_inventory = benchmark / "requirements" / "scored-assertion-inventory.json" + oracle_document = _load_validated(oracle, schemas / "prompt-requirements.schema.json") + if oracle_document.get("freeze_status") != "frozen": + raise ValueError("Prompt requirements oracle must be frozen before building a manifest") + if len(oracle_document.get("independent_reviews", [])) < 2: + raise ValueError("Prompt requirements oracle requires two independent approvals") + _load_validated(scored_inventory, schemas / "scored-assertion-inventory.schema.json") + package_profile = schemas / "canonical-package-hash-v1.json" + scene_graph_profile = schemas / "scene-graph-profile-v1.json" + source_tree_profile = schemas / "grader-source-tree-profile-v1.json" + export_contract = environment_attestation.get("export_contract") + if not isinstance(export_contract, dict): + raise ValueError("Environment attestation has no export contract") + render_profiles = load_render_profiles(schemas) + expected_environment_profiles = environment_profile_hashes(schemas) + if environment_attestation.get("profile_hashes") != expected_environment_profiles: + changed = sorted( + key + for key in set(expected_environment_profiles) + | set(environment_attestation.get("profile_hashes", {})) + if environment_attestation.get("profile_hashes", {}).get(key) + != expected_environment_profiles.get(key) + ) + raise ValueError( + "Environment attestation has stale or substituted profile hashes: " + ", ".join(changed) + ) + if export_contract != render_profiles.export_contract(): + raise ValueError("Environment attestation export contract differs from normative profiles") + expected_source_tree_profile = _sha256(source_tree_profile) + if source_tree_manifest.get("source_tree_profile_sha256") != expected_source_tree_profile: + raise ValueError("Grader source-tree manifest is bound to the wrong profile hash") + if environment_attestation.get("grader_source_tree_sha256") != source_tree_sha256: + raise ValueError("Environment attestation is bound to the wrong grader source-tree hash") + resolved_gold_sha256 = _sha256(resolved_gold) + canonical_package_profile_sha256 = _sha256(package_profile) + scene_graph_profile_sha256 = _sha256(scene_graph_profile) + if ( + environment_attestation.get("profile_hashes", {}).get("scene_graph_profile_sha256") + != scene_graph_profile_sha256 + ): + raise ValueError("Environment attestation is bound to the wrong scene-graph profile") + scene_graph_path = benchmark / "fixtures" / "expected-deck.json" + scene_graph = _load_validated(scene_graph_path, schemas / "scene-graph.schema.json") + if scene_graph.get("profile_sha256") != scene_graph_profile_sha256: + raise ValueError("Gold scene graph is bound to the wrong extraction profile") + if scene_graph.get("mce_resolved_package_sha256") != resolved_gold_sha256: + raise ValueError("Gold scene graph was not extracted from the resolved gold package") + if [slide.get("slide") for slide in scene_graph.get("slides", [])] != list(range(1, 21)): + raise ValueError("Gold scene graph must contain slides exactly 1 through 20") + canonical_png_sha256s = [_sha256(path) for path in exports] + original_gold_sha256 = _sha256(gold_path) + canonical_gold_pdf_sha256 = _sha256(gold_pdf) + canonical_package_hash_v1 = f"sha256:{canonical_package_sha256(resolved_gold, package_profile)}" + expected_determinism_bindings = { + "environment_attestation_sha256": environment_attestation_sha256, + "original_gold_sha256": original_gold_sha256, + "resolved_gold_sha256": resolved_gold_sha256, + "canonical_package_hash_profile_sha256": canonical_package_profile_sha256, + "canonical_package_hash_v1": canonical_package_hash_v1, + "canonical_pdf_sha256": canonical_gold_pdf_sha256, + "canonical_png_sha256s": canonical_png_sha256s, + "export_profile_sha256": environment_attestation.get("profile_hashes", {}).get( + "export_profile_sha256" + ), + "ssim_profile_sha256": environment_attestation.get("profile_hashes", {}).get( + "ssim_profile_sha256" + ), + } + evidence_result = _EvidenceValidationResult() + validate_export_determinism_evidence( + evidence_result, + determinism_evidence, + expected_bindings=expected_determinism_bindings, + ) + if evidence_result.errors: + raise ValueError( + "Invalid export determinism evidence: " + "; ".join(evidence_result.errors) + ) + manifest: dict[str, Any] = { + "schema_version": "1.0", + "manifest_id": "acidslide-scoring-manifest-v1", + "release_status": "frozen", + "benchmark_version": "acidslide-v1.0.0", + "platform": runtime["platform"], + "oci_image_digest": runtime["oci_image_digest"], + "runtime": { + key: runtime[key] + for key in ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + "libfaketime_library_sha256", + "fontconfig_config_sha256", + "environment_attestation_sha256", + ) + } + | { + "locale": "en_US.UTF-8", + "timezone": "UTC", + "reference_datetime": "2025-01-01T00:00:00Z", + "faketime_environment": { + "FAKETIME": "@2025-01-01 00:00:00", + "FAKETIME_DONT_FAKE_MONOTONIC": "1", + "FAKETIME_NO_CACHE": "1", + "LD_PRELOAD": "/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1", + "TZ": "UTC", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US.UTF-8", + }, + }, + "render_profiles": render_profiles.hashes, + "export": render_profiles.scoring_export(), + "visual_comparison": render_profiles.scoring_visual_comparison(), + "structural_profiles": { + "mce_profile_sha256": _sha256(schemas / "mce-profile-v1.json"), + "xsd_bundle_sha256": _tree_sha256(schemas / "ecma-376" / "xsd-transitional"), + "schema_root_map_sha256": _sha256(schemas / "schema-root-map-v1.json"), + "scene_graph_profile_sha256": scene_graph_profile_sha256, + "canonical_package_hash_profile_sha256": _sha256(package_profile), + }, + "artifacts": { + "prompt_bundle_sha256": _tree_sha256(benchmark / "prompts"), + "prompt_requirements_oracle_sha256": _sha256(oracle), + "scored_assertion_inventory_sha256": _sha256(scored_inventory), + "checklist_bundle_sha256": _tree_sha256(benchmark / "checklist"), + "tier_bundle_sha256": _tree_sha256(benchmark / "tiers"), + "asset_bundle_sha256": _tree_sha256(benchmark / "assets"), + "font_bundle_sha256": _tree_sha256(benchmark / "fonts"), + "json_schema_bundle_sha256": _tree_sha256(schemas), + "conformance_fixture_bundle_sha256": _tree_sha256(benchmark / "fixtures"), + "grader_source_tree_sha256": source_tree_sha256, + "grader_source_tree_profile_sha256": expected_source_tree_profile, + "grader_source_tree_manifest_sha256": source_tree_sha256, + "grader_package_sha256": _sha256(grader_package), + }, + "gold": { + "original_byte_sha256": original_gold_sha256, + "mce_resolved_package_sha256": resolved_gold_sha256, + "mce_resolved_package_size_bytes": resolved_gold.stat().st_size, + "canonical_package_hash_profile_sha256": canonical_package_profile_sha256, + "canonical_package_hash_v1": canonical_package_hash_v1, + "scene_graph_sha256": _sha256(scene_graph_path), + "canonical_pdf_sha256": canonical_gold_pdf_sha256, + "canonical_png_sha256s": canonical_png_sha256s, + "export_bundle_sha256": _tree_sha256(gold_exports), + "export_determinism_evidence_sha256": _jcs_sha256(determinism_evidence), + "expected_export_count": 20, + }, + } + schema = json.loads((schemas / "scoring-manifest.schema.json").read_text(encoding="utf-8")) + jsonschema.Draft202012Validator(schema).validate(manifest) + return manifest + + +def main() -> None: + args = _arguments() + manifest = build_manifest( + runtime_path=args.runtime, + gold_path=args.gold, + gold_exports=args.gold_exports, + resolved_gold=args.resolved_gold, + gold_pdf=args.gold_pdf, + environment_attestation_path=args.environment_attestation, + export_determinism_evidence_path=args.export_determinism_evidence, + grader_source_tree_manifest_path=args.grader_source_tree_manifest, + grader_package=args.grader_package, + ) + encoded = rfc8785.dumps(manifest) + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_bytes(encoded) + print(f"wrote {args.output}") + print(f"scoring_manifest_sha256=sha256:{hashlib.sha256(encoded).hexdigest()}") + + +if __name__ == "__main__": + main() diff --git a/acidslide-v1/benchmark/validate_corpus.py b/acidslide-v1/benchmark/validate_corpus.py new file mode 100644 index 0000000..41c170d --- /dev/null +++ b/acidslide-v1/benchmark/validate_corpus.py @@ -0,0 +1,862 @@ +#!/usr/bin/env python3 +"""Validate the public, non-gold AcidSlide v1 benchmark corpus.""" + +from __future__ import annotations + +import argparse +import collections +import hashlib +import json +import re +import struct +import sys +from pathlib import Path + +import jsonschema +import yaml +from validate_normative import validate_normative + +BENCHMARK = Path(__file__).resolve().parent +ROOT = BENCHMARK.parent +TOKEN_PATTERN = re.compile( + r"#[0-9A-Fa-f]{6}|[A-Za-z0-9_-]+\.(?:png|pptx)|\d+(?:\.\d+)?(?:cm|pt|px|mm|%|°|×)|`[^`\n]+`|\"[^\"\n]+\"|[\u0600-\u06ff]+|[\u3040-\u30ff\u3400-\u9fff]+" +) + + +class Validation: + def __init__(self) -> None: + self.errors: list[str] = [] + self.notes: list[str] = [] + + def require(self, condition: bool, message: str) -> None: + if not condition: + self.errors.append(message) + + +def digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def png_size(path: Path) -> list[int]: + data = path.read_bytes()[:24] + if len(data) != 24 or data[:8] != b"\x89PNG\r\n\x1a\n" or data[12:16] != b"IHDR": + raise ValueError(f"not a PNG: {path}") + return list(struct.unpack(">II", data[16:24])) + + +def validate_assets(result: Validation) -> dict[str, str]: + path = BENCHMARK / "assets" / "manifest.json" + result.require(path.is_file(), "assets/manifest.json is missing") + if not path.is_file(): + return {} + manifest = json.loads(path.read_text(encoding="utf-8")) + assets = manifest.get("assets", []) + result.require( + manifest.get("policy") == "allowlist-only", + "asset manifest policy must be allowlist-only", + ) + result.require(len(assets) == 3, f"expected 3 assets, found {len(assets)}") + hashes: dict[str, str] = {} + for entry in assets: + asset_id = entry.get("asset_id", "") + local = BENCHMARK / "assets" / entry.get("local_path", "") + source = BENCHMARK / "assets" / entry.get("source_path", "") + license_path = BENCHMARK / "assets" / entry.get("license_file", "") + result.require(local.is_file(), f"asset {asset_id}: local file missing") + result.require(source.is_file(), f"asset {asset_id}: source file missing") + result.require(license_path.is_file(), f"asset {asset_id}: license file missing") + result.require(entry.get("license") == "CC0-1.0", f"asset {asset_id}: expected CC0-1.0") + result.require( + entry.get("source_url") is None, + f"asset {asset_id}: self-authored source_url must be null", + ) + result.require( + entry.get("accepted_recompression_hashes") == [], + f"asset {asset_id}: recompression hashes must remain empty until gold extraction", + ) + result.require( + entry.get("recompression_status") == "pending_gold_deck_extraction", + f"asset {asset_id}: recompression status is dishonest", + ) + if local.is_file(): + actual = digest(local) + hashes[asset_id] = actual + result.require(actual == entry.get("sha256"), f"asset {asset_id}: SHA-256 mismatch") + result.require( + png_size(local) == entry.get("dimensions_px"), + f"asset {asset_id}: PNG dimensions mismatch", + ) + if source.is_file(): + result.require( + digest(source) == entry.get("source_sha256"), + f"asset {asset_id}: source SHA-256 mismatch", + ) + return hashes + + +def validate_fonts(result: Validation) -> None: + path = BENCHMARK / "fonts" / "manifest.json" + result.require(path.is_file(), "fonts/manifest.json is missing") + result.require((BENCHMARK / "fonts" / "LICENSE").is_file(), "fonts/LICENSE is missing") + if not path.is_file(): + return + manifest = json.loads(path.read_text(encoding="utf-8")) + packages = manifest.get("packages", []) + files = manifest.get("files", []) + result.require( + manifest.get("runtime") == "Ubuntu 22.04 (jammy)", + "font runtime must match canonical Ubuntu 22.04", + ) + result.require(len(packages) == 5, f"expected 5 pinned font packages, found {len(packages)}") + result.require(len(files) == 26, f"expected 26 bundled font files, found {len(files)}") + families = {entry.get("family") for entry in files} + required_families = { + "Liberation Sans", + "Liberation Serif", + "Liberation Mono", + "Carlito", + "Caladea", + "Noto Sans", + "Noto Sans Arabic", + "Noto Sans CJK JP", + } + result.require( + required_families <= families, + f"font families missing: {sorted(required_families - families)}", + ) + for package in packages: + result.require( + str(package.get("source_url", "")).startswith("https://archive.ubuntu.com/ubuntu/"), + f"font package {package.get('package')}: source is not pinned Ubuntu archive", + ) + result.require( + re.fullmatch(r"[0-9a-f]{64}", package.get("package_sha256", "")) is not None, + f"font package {package.get('package')}: package hash invalid", + ) + result.require( + (BENCHMARK / "fonts" / package.get("license_file", "")).is_file(), + f"font package {package.get('package')}: license file missing", + ) + for entry in files: + local = BENCHMARK / "fonts" / entry.get("local_path", "") + result.require(local.is_file(), f"font file missing: {entry.get('local_path')}") + if local.is_file(): + result.require( + digest(local) == entry.get("sha256"), + f"font hash mismatch: {entry.get('local_path')}", + ) + + +def hard_tokens(text: str) -> list[str]: + return sorted(TOKEN_PATTERN.findall(text)) + + +def _prompt_validation_metadata(result: Validation, record: Path, slide: int) -> dict: + text = record.read_text(encoding="utf-8") + match = re.match( + r"\A\n", + text, + re.DOTALL, + ) + result.require(match is not None, f"slide {slide:02d}: machine validation header missing") + if match is None: + return {} + try: + metadata = json.loads(match.group(1)) + except json.JSONDecodeError as error: + result.errors.append(f"slide {slide:02d}: invalid validation metadata: {error}") + return {} + result.require( + isinstance(metadata, dict), + f"slide {slide:02d}: validation metadata must be an object", + ) + return metadata if isinstance(metadata, dict) else {} + + +def _prompt_evidence_path(result: Validation, value: object, slide: int, label: str) -> Path | None: + if not isinstance(value, str) or not value: + result.errors.append(f"slide {slide:02d}: {label} must be a nonempty relative path") + return None + candidate = (BENCHMARK / value).resolve() + evidence_root = (BENCHMARK / "fixtures" / "prompt-validation").resolve() + if not candidate.is_relative_to(evidence_root): + result.errors.append( + f"slide {slide:02d}: {label} must stay under fixtures/prompt-validation" + ) + return None + result.require(candidate.is_file(), f"slide {slide:02d}: {label} is missing: {value}") + return candidate if candidate.is_file() else None + + +def _validate_prompt_assertion_report( + result: Validation, + *, + path: Path, + expected_sha256: object, + slide: int, + round_id: str, + author: dict, + prompt_hash: str, + expected_requirement_ids: list[str], +) -> None: + result.require( + expected_sha256 == f"sha256:{digest(path)}", + f"slide {slide:02d}: assertion report hash mismatch for {author.get('author_id')}", + ) + try: + report = json.loads(path.read_text(encoding="utf-8")) + except (UnicodeDecodeError, json.JSONDecodeError) as error: + result.errors.append(f"slide {slide:02d}: invalid assertion report {path}: {error}") + return + required_keys = { + "schema_version", + "report_id", + "round_id", + "slide", + "author_id", + "prompt_variant", + "prompt_sha256", + "artifact_sha256", + "resolved_package_sha256", + "scene_graph_sha256", + "results", + } + result.require( + isinstance(report, dict) and set(report) == required_keys, + f"slide {slide:02d}: assertion report has missing or unknown fields", + ) + if not isinstance(report, dict): + return + result.require(report.get("schema_version") == "1.0", f"slide {slide:02d}: report version") + result.require(report.get("round_id") == round_id, f"slide {slide:02d}: report round drift") + result.require(report.get("slide") == slide, f"slide {slide:02d}: report slide drift") + for field in ( + "author_id", + "prompt_variant", + "artifact_sha256", + "resolved_package_sha256", + "scene_graph_sha256", + ): + result.require( + report.get(field) == author.get(field), + f"slide {slide:02d}: report {field} does not match author handoff", + ) + result.require( + report.get("prompt_sha256") == prompt_hash, + f"slide {slide:02d}: report prompt hash drift", + ) + rows = report.get("results") + result.require(isinstance(rows, list), f"slide {slide:02d}: report results must be an array") + if not isinstance(rows, list): + return + observed_ids: list[str] = [] + for row in rows: + result.require( + isinstance(row, dict) and set(row) == {"requirement_id", "passed", "evidence_ids"}, + f"slide {slide:02d}: malformed assertion-result row", + ) + if not isinstance(row, dict): + continue + requirement_id = row.get("requirement_id") + if isinstance(requirement_id, str): + observed_ids.append(requirement_id) + result.require(row.get("passed") is True, f"slide {slide:02d}: failed mandatory assertion") + evidence_ids = row.get("evidence_ids") + result.require( + isinstance(evidence_ids, list) + and bool(evidence_ids) + and all(isinstance(item, str) and item for item in evidence_ids), + f"slide {slide:02d}: assertion result lacks concrete evidence IDs", + ) + result.require( + sorted(observed_ids) == expected_requirement_ids, + f"slide {slide:02d}: assertion report does not cover the exact prompt requirements", + ) + + +def _validate_completed_prompt_round( + result: Validation, + *, + metadata: dict, + slide: int, + expected_requirement_ids: list[str], +) -> None: + round_id = metadata.get("round_id") + result.require( + isinstance(round_id, str) + and re.fullmatch(r"[a-z0-9][a-z0-9._-]{2,127}", round_id) is not None, + f"slide {slide:02d}: completed round_id is invalid", + ) + if not isinstance(round_id, str): + return + authors = metadata.get("authors") + result.require( + isinstance(authors, list) and len(authors) == 3, + f"slide {slide:02d}: completed round must have exactly three authors", + ) + if not isinstance(authors, list) or len(authors) != 3: + return + required_author_keys = { + "author_id", + "prompt_variant", + "clean_context", + "artifact_path", + "artifact_sha256", + "resolved_package_sha256", + "scene_graph_sha256", + "assertion_report_path", + "assertion_report_sha256", + "mandatory_assertions_total", + "mandatory_assertions_passed", + } + author_ids: list[str] = [] + variants: list[str] = [] + prompt_hashes = metadata.get("prompt_hashes", {}) + for author in authors: + result.require( + isinstance(author, dict) and set(author) == required_author_keys, + f"slide {slide:02d}: author handoff has missing or unknown fields", + ) + if not isinstance(author, dict): + continue + author_id = author.get("author_id") + variant = author.get("prompt_variant") + if isinstance(author_id, str): + author_ids.append(author_id) + if isinstance(variant, str): + variants.append(variant) + result.require(author.get("clean_context") is True, f"slide {slide:02d}: author not blind") + total = author.get("mandatory_assertions_total") + passed = author.get("mandatory_assertions_passed") + result.require( + total == len(expected_requirement_ids) and passed == total, + f"slide {slide:02d}: author did not pass every mandatory assertion", + ) + for field in ( + "artifact_sha256", + "resolved_package_sha256", + "scene_graph_sha256", + ): + result.require( + isinstance(author.get(field), str) + and re.fullmatch(r"sha256:[0-9a-f]{64}", author[field]) is not None, + f"slide {slide:02d}: author {field} is invalid", + ) + artifact = _prompt_evidence_path( + result, author.get("artifact_path"), slide, "author artifact" + ) + if artifact is not None: + result.require( + author.get("artifact_sha256") == f"sha256:{digest(artifact)}", + f"slide {slide:02d}: author artifact hash mismatch", + ) + report_path = _prompt_evidence_path( + result, author.get("assertion_report_path"), slide, "assertion report" + ) + prompt_hash = prompt_hashes.get(variant) if isinstance(prompt_hashes, dict) else None + if report_path is not None and isinstance(prompt_hash, str): + _validate_prompt_assertion_report( + result, + path=report_path, + expected_sha256=author.get("assertion_report_sha256"), + slide=slide, + round_id=round_id, + author=author, + prompt_hash=prompt_hash, + expected_requirement_ids=expected_requirement_ids, + ) + result.require(len(set(author_ids)) == 3, f"slide {slide:02d}: author IDs are not unique") + result.require( + set(variants) == {"canonical", "paraphrase-a", "paraphrase-b"}, + f"slide {slide:02d}: completed round must cover all three prompt variants", + ) + diagnostics = metadata.get("pairwise_similarity_diagnostics") + result.require( + isinstance(diagnostics, list) and len(diagnostics) == 3, + f"slide {slide:02d}: expected exactly three pairwise diagnostics", + ) + observed_pairs: set[tuple[str, str]] = set() + if isinstance(diagnostics, list): + for diagnostic in diagnostics: + result.require( + isinstance(diagnostic, dict) + and set(diagnostic) == {"author_a", "author_b", "scene_graph_similarity"}, + f"slide {slide:02d}: malformed similarity diagnostic", + ) + if not isinstance(diagnostic, dict): + continue + a = diagnostic.get("author_a") + b = diagnostic.get("author_b") + similarity = diagnostic.get("scene_graph_similarity") + if isinstance(a, str) and isinstance(b, str) and a != b: + observed_pairs.add(tuple(sorted((a, b)))) + result.require( + isinstance(similarity, (int, float)) + and not isinstance(similarity, bool) + and 0 <= similarity <= 1, + f"slide {slide:02d}: invalid diagnostic similarity", + ) + result.require( + len(observed_pairs) == 3, + f"slide {slide:02d}: pairwise diagnostics do not cover all author pairs", + ) + + +def validate_prompts(result: Validation, release: bool) -> None: + deck = BENCHMARK / "prompts" / "deck.md" + brief = BENCHMARK / "prompts" / "DESIGNER_BRIEF.md" + result.require(deck.is_file(), "prompts/deck.md is missing") + result.require(brief.is_file(), "prompts/DESIGNER_BRIEF.md is missing") + if brief.is_file(): + text = brief.read_text(encoding="utf-8") + result.require( + "Author in Microsoft PowerPoint" not in text, + "designer brief still instructs PowerPoint-first authoring", + ) + result.require( + "derived from the gold" not in text.lower(), + "designer brief says prompts derive from gold", + ) + result.require( + "pinned LibreOffice Impress environment" in text, + "designer brief lacks LibreOffice-only authoring contract", + ) + result.require( + "grading-verified" in text and "generation-attested" in text, + "designer brief lacks current verification terminology", + ) + result.require( + "Noto Sans JP" not in text, + "designer brief uses the unbundled Noto Sans JP family name", + ) + result.require( + "Noto Sans CJK JP" in text, + "designer brief lacks the bundled Noto Sans CJK JP family name", + ) + result.require( + "will be provided" not in text, + "designer brief still describes bundled assets as future deliveries", + ) + variant_files = list((BENCHMARK / "prompts" / "variants").glob("*/slide-*.md")) + validation_files = list((BENCHMARK / "prompts" / "validation").glob("slide-*.md")) + result.require( + len(variant_files) == 60, + f"expected exactly 60 slide prompt variants, found {len(variant_files)}", + ) + result.require( + len(validation_files) == 20, + f"expected exactly 20 prompt validation records, found {len(validation_files)}", + ) + oracle_path = BENCHMARK / "requirements" / "prompt-requirements.json" + oracle = json.loads(oracle_path.read_text(encoding="utf-8")) if oracle_path.is_file() else {} + requirements_by_slide = { + slide: sorted( + item.get("requirement_id") + for item in oracle.get("requirements", []) + if item.get("scope") == "slide" and item.get("slide") == slide + ) + for slide in range(1, 21) + } + pending = 0 + for number in range(1, 21): + paths = { + name: BENCHMARK / "prompts" / "variants" / name / f"slide-{number:02d}.md" + for name in ("canonical", "paraphrase-a", "paraphrase-b") + } + for name, path in paths.items(): + result.require(path.is_file(), f"slide {number:02d}: missing {name} prompt") + if all(path.is_file() for path in paths.values()): + texts = {name: path.read_text(encoding="utf-8") for name, path in paths.items()} + result.require( + all("primary directive" in text for text in texts.values()), + f"slide {number:02d}: prompt-first authority missing", + ) + result.require( + all("Noto Sans JP" not in text for text in texts.values()), + f"slide {number:02d}: prompt uses unbundled Noto Sans JP family", + ) + canonical_tokens = hard_tokens(texts["canonical"]) + result.require( + hard_tokens(texts["paraphrase-a"]) == canonical_tokens, + f"slide {number:02d}: paraphrase A hard-constraint drift", + ) + result.require( + hard_tokens(texts["paraphrase-b"]) == canonical_tokens, + f"slide {number:02d}: paraphrase B hard-constraint drift", + ) + canonical_blocks = re.findall(r"```.*?```", texts["canonical"], re.DOTALL) + result.require( + re.findall(r"```.*?```", texts["paraphrase-a"], re.DOTALL) == canonical_blocks, + f"slide {number:02d}: paraphrase A changed a literal code/text block", + ) + result.require( + re.findall(r"```.*?```", texts["paraphrase-b"], re.DOTALL) == canonical_blocks, + f"slide {number:02d}: paraphrase B changed a literal code/text block", + ) + result.require( + len({texts[name] for name in texts}) == 3, + f"slide {number:02d}: variants are not distinct", + ) + record = BENCHMARK / "prompts" / "validation" / f"slide-{number:02d}.md" + result.require(record.is_file(), f"slide {number:02d}: validation record missing") + if record.is_file(): + record_text = record.read_text(encoding="utf-8") + metadata = _prompt_validation_metadata(result, record, number) + expected_metadata_keys = { + "schema_version", + "record_id", + "slide", + "prompt_hashes", + "status", + "round_id", + "authors", + "pairwise_similarity_diagnostics", + } + result.require( + set(metadata) == expected_metadata_keys, + f"slide {number:02d}: validation metadata has missing or unknown fields", + ) + result.require( + metadata.get("schema_version") == "1.0" + and metadata.get("record_id") == f"acidslide-prompt-validation-slide-{number:02d}" + and metadata.get("slide") == number, + f"slide {number:02d}: validation metadata identity mismatch", + ) + expected_hashes = {name: f"sha256:{digest(path)}" for name, path in paths.items()} + result.require( + metadata.get("prompt_hashes") == expected_hashes, + f"slide {number:02d}: validation record prompt hash drift", + ) + status = metadata.get("status") + result.require( + status in {"pending", "completed"}, + f"slide {number:02d}: invalid validation status", + ) + result.require( + "hard-constraint parity: pass" in record_text, + f"slide {number:02d}: static parity not passed", + ) + result.require( + "does not claim authoring convergence" in record_text, + f"slide {number:02d}: convergence disclaimer missing", + ) + result.require( + "Required blinded author count: 3" in record_text, + f"slide {number:02d}: three-author requirement missing", + ) + result.require( + "Structural similarity: diagnostic only; no release threshold" in record_text, + f"slide {number:02d}: diagnostic-only similarity rule missing", + ) + result.require( + "80% structural similarity" not in record_text, + f"slide {number:02d}: stale similarity release threshold remains", + ) + if status == "pending": + pending += 1 + result.require( + metadata.get("round_id") is None + and metadata.get("authors") == [] + and metadata.get("pairwise_similarity_diagnostics") == [], + f"slide {number:02d}: pending record contains claimed run evidence", + ) + result.require( + "Independent-author convergence: not run" in record_text, + f"slide {number:02d}: pending status disclaimer missing", + ) + elif status == "completed": + result.require( + "Independent-author convergence: completed" in record_text, + f"slide {number:02d}: completed human-readable status missing", + ) + _validate_completed_prompt_round( + result, + metadata=metadata, + slide=number, + expected_requirement_ids=requirements_by_slide[number], + ) + result.notes.append(f"independent-author convergence pending: {pending}/20") + if release: + result.require( + pending == 0, + f"release mode: {pending} prompt convergence records are still pending", + ) + + +def validate_checklist(result: Validation, release: bool = False) -> None: + schema = json.loads( + (ROOT / "schemas" / "checklist-item.schema.json").read_text(encoding="utf-8") + ) + validator = jsonschema.Draft202012Validator(schema) + paths = [BENCHMARK / "checklist" / "deck.yaml"] + sorted( + (BENCHMARK / "checklist" / "slides").glob("slide-*.yaml") + ) + documents: list[dict] = [] + by_path: dict[Path, list[dict]] = {} + for path in paths: + docs = [ + doc for doc in yaml.safe_load_all(path.read_text(encoding="utf-8")) if doc is not None + ] + by_path[path] = docs + documents.extend(docs) + for doc in docs: + for error in validator.iter_errors(doc): + result.errors.append( + f"{path.name}:{doc.get('id', '')}: schema: {error.message}" + ) + deck_count = len(by_path[BENCHMARK / "checklist" / "deck.yaml"]) + result.require(deck_count == 20, f"expected 20 deck items, found {deck_count}") + for number in range(1, 21): + path = BENCHMARK / "checklist" / "slides" / f"slide-{number:02d}.yaml" + result.require( + len(by_path.get(path, [])) == 13, + f"slide {number:02d}: expected 13 items, found {len(by_path.get(path, []))}", + ) + result.require(len(documents) == 280, f"expected 280 checklist items, found {len(documents)}") + ids = [doc.get("id") for doc in documents] + duplicates = [key for key, count in collections.Counter(ids).items() if count > 1] + result.require(not duplicates, f"duplicate checklist IDs: {duplicates}") + severity = collections.Counter(doc.get("severity") for doc in documents) + result.require( + severity == {"critical": 84, "major": 112, "minor": 84}, + f"severity mix must be exact 30/40/30, found {dict(severity)}", + ) + sources = collections.Counter(doc.get("source_of_truth") for doc in documents) + result.require( + all(sources[key] >= 70 for key in ("ooxml", "render", "both")), + f"source split is not balanced enough: {dict(sources)}", + ) + result.require( + sources["render"] + sources["both"] >= 160, + f"render-aware item volume too low: {dict(sources)}", + ) + for doc in documents: + if doc.get("verification", {}).get("method") == "visual_ssim": + result.require( + doc["verification"].get("expectation", {}).get("min_ssim") == 0.9999, + f"{doc.get('id')}: SSIM threshold is not 0.9999", + ) + candidate_count = sum(doc.get("lifecycle_state") != "frozen" for doc in documents) + pending_provenance_count = sum( + doc.get("provenance", {}).get("status") != "complete" for doc in documents + ) + pending_evidence_count = sum( + doc.get("evidence", {}).get("status") != "complete" for doc in documents + ) + pending_affected_slides_count = sum( + doc.get("failure_mode", {}).get("affected_slides", {}).get("status") != "complete" + for doc in documents + if "failure_mode" in doc + ) + result.notes.append( + "checklist release state: " + f"lifecycle_not_frozen={candidate_count}, " + f"provenance_not_complete={pending_provenance_count}, " + f"evidence_not_complete={pending_evidence_count}, " + f"affected_slides_not_complete={pending_affected_slides_count}" + ) + if release: + result.require( + candidate_count == 0, + f"release mode: {candidate_count} checklist items are not frozen", + ) + result.require( + pending_provenance_count == 0, + "release mode: " + f"{pending_provenance_count} checklist provenance records are not complete", + ) + result.require( + pending_evidence_count == 0, + f"release mode: {pending_evidence_count} checklist evidence records are not complete", + ) + result.require( + pending_affected_slides_count == 0, + "release mode: " + f"{pending_affected_slides_count} automatic-fail affected-slide mappings " + "are not complete", + ) + + +def validate_mutation_fixtures(result: Validation) -> None: + """Validate generated operator coverage without treating it as release evidence.""" + fixture_dir = BENCHMARK / "fixtures" / "mutations" + paths = { + "index": fixture_dir / "fixture-index-v1.json", + "expectations": fixture_dir / "mutation-expectations-v1.json", + "execution": fixture_dir / "execution-report-v1.json", + } + for label, path in paths.items(): + result.require(path.is_file(), f"generated mutation {label} is missing: {path}") + if not all(path.is_file() for path in paths.values()): + return + + index = json.loads(paths["index"].read_text(encoding="utf-8")) + expectations = json.loads(paths["expectations"].read_text(encoding="utf-8")) + execution = json.loads(paths["execution"].read_text(encoding="utf-8")) + index_entries = index.get("entries", []) + expectation_entries = expectations.get("expectations", []) + execution_entries = execution.get("results", []) + item_ids = [entry.get("checklist_item_id") for entry in index_entries] + + result.require(len(index_entries) == 280, "mutation fixture index must contain 280 entries") + result.require(len(set(item_ids)) == 280, "mutation fixture checklist IDs must be unique") + result.require( + index.get("summary", {}).get("executable_items") == 280, + "all 280 current checklist operators must have executable generated fixtures", + ) + result.require( + index.get("summary", {}).get("assertion_evidence_complete") == 0, + "generated operator fixtures must not claim independent assertion evidence", + ) + result.require( + all(entry.get("release_evidence_claimed") is False for entry in index_entries), + "fixture index contains a fabricated release-evidence claim", + ) + result.require( + len(expectation_entries) == 280 + and all(entry.get("fault_count") == 1 for entry in expectation_entries), + "mutation expectations must contain 280 single-fault records", + ) + result.require( + all(entry.get("release_evidence_claimed") is False for entry in expectation_entries), + "mutation expectations contain a fabricated release-evidence claim", + ) + result.require( + len(execution_entries) == 280 + and all(entry.get("positive_passed") is True for entry in execution_entries) + and all(entry.get("negative_passed") is False for entry in execution_entries) + and all(entry.get("mutant_killed") is True for entry in execution_entries), + "generated mutation execution must pass 280 positives and kill 280 negatives", + ) + result.require( + execution.get("summary", {}).get("assertion_evidence_completed_by_this_run") == 0, + "generated execution report must not complete assertion evidence", + ) + + registry_path = BENCHMARK / "requirements" / "affected-slide-selectors-v1.json" + result.require(registry_path.is_file(), "affected-slide selector registry is missing") + if registry_path.is_file(): + registry = json.loads(registry_path.read_text(encoding="utf-8")) + bindings: dict[str, str] = {} + for entry in registry.get("selectors", []): + descriptor_bytes = json.dumps( + entry.get("descriptor"), + ensure_ascii=False, + sort_keys=True, + separators=(",", ":"), + ).encode() + actual_hash = f"sha256:{hashlib.sha256(descriptor_bytes).hexdigest()}" + selector_id = entry.get("selector_id", "") + result.require( + entry.get("selector_sha256") == actual_hash, + f"affected-slide selector hash mismatch: {selector_id}", + ) + bindings[selector_id] = actual_hash + deck_documents = { + document["id"]: document + for document in yaml.safe_load_all( + (BENCHMARK / "checklist" / "deck.yaml").read_text(encoding="utf-8") + ) + if document is not None + } + for item_id in ("deck.font-policy", "deck.no-notes"): + affected = deck_documents[item_id]["failure_mode"]["affected_slides"] + result.require( + affected.get("status") == "complete" + and affected.get("mode") == "named_selector" + and affected.get("slides") == [] + and bindings.get(affected.get("selector_id")) == affected.get("selector_sha256"), + f"{item_id}: named affected-slide binding is incomplete or stale", + ) + for entry in index_entries: + if entry.get("checklist_item_id") not in { + "deck.font-policy", + "deck.no-notes", + }: + continue + result.require( + entry.get("operator_coverage_status") == "executable", + f"{entry.get('checklist_item_id')}: affected-slide operator is not executable", + ) + + result.notes.append( + "generated operator fixtures: 280/280 positives passed, 280/280 single-fault " + "mutants killed; independent assertion evidence completed=0/280" + ) + + +def validate_tiers(result: Validation) -> None: + expected = {1: list(range(1, 6)), 2: list(range(1, 13)), 3: list(range(1, 21))} + for tier, slides in expected.items(): + path = BENCHMARK / "tiers" / f"level-{tier}" / "slides.json" + result.require(path.is_file(), f"tier {tier}: slides.json is missing") + if path.is_file(): + payload = json.loads(path.read_text(encoding="utf-8")) + result.require(payload.get("tier") == tier, f"tier {tier}: tier field mismatch") + result.require( + payload.get("slides") == slides, + f"tier {tier}: expected prefix {slides}, found {payload.get('slides')}", + ) + + +def validate_release_documents(result: Validation, release: bool) -> None: + """Require explicit public-document freeze state for a release build.""" + if not release: + return + repository = ROOT.parent + openspec = repository / "ACIDSLIDE_OPENSPEC.md" + readme = repository / "README.md" + result.require(openspec.is_file(), "release mode: ACIDSLIDE_OPENSPEC.md is missing") + result.require(readme.is_file(), "release mode: README.md is missing") + if openspec.is_file(): + status_lines = [ + line + for line in openspec.read_text(encoding="utf-8").splitlines() + if line.startswith("Status:") + ] + result.require( + status_lines == ["Status: Frozen — acidslide-v1.0.0"], + "release mode: OpenSpec status must be exactly 'Status: Frozen — acidslide-v1.0.0'", + ) + if readme.is_file(): + result.require( + "> **Pre-release status:**" not in readme.read_text(encoding="utf-8"), + "release mode: README still declares pre-release status", + ) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "--release", + action="store_true", + help="also require completed independent-author prompt convergence", + ) + args = parser.parse_args() + result = Validation() + validate_assets(result) + validate_fonts(result) + validate_prompts(result, args.release) + validate_checklist(result, args.release) + validate_mutation_fixtures(result) + validate_tiers(result) + validate_normative(result, args.release) + validate_release_documents(result, args.release) + if result.errors: + print("AcidSlide corpus validation: FAIL") + for error in result.errors: + print(f"- {error}") + for note in result.notes: + print(f"- note: {note}") + return 1 + print("AcidSlide corpus validation: PASS") + print("- prompts: 1 deck + 60 slide variants + 20 validation records") + print("- checklist: 280 unique schema-valid items; severity 84/112/84 (30/40/30)") + print("- manifests: 3 CC0 assets + 26 redistributable pinned font files") + for note in result.notes: + print(f"- note: {note}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/acidslide-v1/benchmark/validate_normative.py b/acidslide-v1/benchmark/validate_normative.py new file mode 100644 index 0000000..2afa3d9 --- /dev/null +++ b/acidslide-v1/benchmark/validate_normative.py @@ -0,0 +1,1175 @@ +"""Validate AcidSlide v1 normative profiles and candidate/frozen artifacts.""" + +# ruff: noqa: E402 + +from __future__ import annotations + +import hashlib +import json +import sys +from base64 import b64decode +from binascii import Error as Base64Error +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Protocol + +import jsonschema +import rfc8785 +import yaml +from referencing import Registry, Resource + +BENCHMARK = Path(__file__).resolve().parent +ROOT = BENCHMARK.parent +GRADER = ROOT / "grader" +SCHEMAS = ROOT / "schemas" +sys.path.insert(0, str(GRADER)) + +from acidslide.profile_contract import ( # noqa: E402 + environment_profile_hashes, + load_render_profiles, +) +from acidslide.release_evidence import ( + validate_assertion_inventory_approvals as _validate_assertion_inventory_approvals, +) +from acidslide.release_evidence import ( + validate_export_determinism_evidence, +) +from acidslide.release_evidence import ( + validate_prompt_review_approvals as _validate_prompt_review_approvals, +) + + +class Result(Protocol): + errors: list[str] + notes: list[str] + + def require(self, condition: bool, message: str) -> None: ... + + +def _local_schema_registry() -> Registry: + registry = Registry() + for path in sorted(SCHEMAS.glob("*.schema.json")): + document = json.loads(path.read_text(encoding="utf-8")) + identifier = document.get("$id") + if isinstance(identifier, str): + registry = registry.with_resource(identifier, Resource.from_contents(document)) + return registry + + +def _validator(schema: dict) -> jsonschema.Draft202012Validator: + return jsonschema.Draft202012Validator( + schema, + registry=_local_schema_registry(), + format_checker=jsonschema.FormatChecker(), + ) + + +def _digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def _validate_json(result: Result, data_name: str, schema_name: str) -> dict: + data_path = SCHEMAS / data_name + if not data_path.is_file(): + data_path = BENCHMARK / data_name + schema_path = SCHEMAS / schema_name + result.require(data_path.is_file(), f"normative artifact missing: {data_path}") + result.require(schema_path.is_file(), f"normative schema missing: {schema_path}") + if not data_path.is_file() or not schema_path.is_file(): + return {} + try: + data = json.loads(data_path.read_text(encoding="utf-8")) + schema = json.loads(schema_path.read_text(encoding="utf-8")) + jsonschema.Draft202012Validator.check_schema(schema) + errors = sorted(_validator(schema).iter_errors(data), key=str) + for error in errors: + result.errors.append(f"{data_path.name}: schema: {error.message}") + return data + except (json.JSONDecodeError, jsonschema.SchemaError) as error: + result.errors.append(f"{data_path.name}: {error}") + return {} + + +def validate_normative(result: Result, release: bool) -> None: + export_profile = _validate_json( + result, + "export-profile-v1.json", + "export-profile.schema.json", + ) + png_profile = _validate_json( + result, + "png-profile-v1.json", + "png-profile.schema.json", + ) + ssim_profile = _validate_json( + result, + "ssim-profile-v1.json", + "ssim-profile.schema.json", + ) + mce = _validate_json(result, "mce-profile-v1.json", "mce-profile.schema.json") + root_map = _validate_json( + result, + "schema-root-map-v1.json", + "schema-root-map.schema.json", + ) + package_profile = _validate_json( + result, + "canonical-package-hash-v1.json", + "canonical-package-hash-profile.schema.json", + ) + scene_profile = _validate_json( + result, + "scene-graph-profile-v1.json", + "scene-graph-profile.schema.json", + ) + _validate_json( + result, + "fixtures/package-hash/gold-copy-rejection-v1.json", + "package-hash-fixture.schema.json", + ) + oracle = _validate_json( + result, + "requirements/prompt-requirements.json", + "prompt-requirements.schema.json", + ) + + for schema_path in sorted(SCHEMAS.glob("*.schema.json")): + try: + schema = json.loads(schema_path.read_text(encoding="utf-8")) + jsonschema.Draft202012Validator.check_schema(schema) + except (json.JSONDecodeError, jsonschema.SchemaError) as error: + result.errors.append(f"{schema_path.name}: invalid JSON Schema: {error}") + + understood = mce.get("understood_namespaces", []) + result.require( + len(understood) == len(set(understood)) and len(understood) >= 7, + "MCE profile must contain a unique explicit understood-namespace set", + ) + entries = root_map.get("entries", []) + mapping_keys = [(entry.get("content_type"), entry.get("root_qname")) for entry in entries] + result.require( + len(mapping_keys) == len(set(mapping_keys)), + "schema/root map has duplicate keys", + ) + for entry in entries: + xsd = SCHEMAS / "ecma-376" / "xsd-transitional" / entry.get("xsd", "") + result.require(xsd.is_file(), f"schema/root map names missing XSD: {xsd.name}") + result.require( + package_profile.get("stage_0_5_resolution", {}).get("mce_profile") == "mce-profile-v1.json", + "canonical package hash is not bound to the v1 MCE profile", + ) + result.require( + package_profile.get("stage_0_5_resolution", {}).get("schema_root_map") + == "schema-root-map-v1.json", + "canonical package hash is not bound to the v1 schema/root map", + ) + result.require( + scene_profile.get("input_contract", {}).get("package_state") == "mce-resolved" + and scene_profile.get("input_contract", {}).get("mce_namespace_policy") + == "reject-elements-and-attributes" + and scene_profile.get("serialization", {}).get("canonicalization") == "RFC8785-JCS", + "scene-graph profile does not freeze resolved input and JCS output", + ) + result.require( + export_profile.get("fresh_isolated_user_profile_per_export") is True + and export_profile.get("libreoffice_command", [None, None, None])[2] + == "-env:UserInstallation=file://", + "export profile does not freeze a fresh isolated LibreOffice profile", + ) + result.require( + png_profile.get("width_px") == 1920 + and png_profile.get("height_px") == 1080 + and png_profile.get("color_mode") == "RGB" + and png_profile.get("encoder", {}).get("compress_level") == 9, + "PNG profile does not freeze the canonical raster and encoder contract", + ) + result.require( + ssim_profile.get("threshold") == 0.9999 + and ssim_profile.get("shape") == [1080, 1920, 3] + and ssim_profile.get("dimension_mismatch") == "fail-with-zero-similarity", + "SSIM profile does not freeze the canonical comparison contract", + ) + + _validate_oracle(result, oracle) + if release: + result.require( + oracle.get("freeze_status") == "frozen", + "release mode: prompt requirements oracle is not frozen", + ) + _validate_prompt_review_approvals(result, oracle) + gold_evidence = _validate_json( + result, + "gold-evidence.json", + "gold-evidence.schema.json", + ) + _validate_gold_evidence_semantics(result, gold_evidence) + determinism_evidence, environment_attestation = _validate_release_evidence_instances( + result, + oracle, + gold_evidence, + ) + _validate_frozen_release_files( + result, + gold_evidence, + determinism_evidence, + environment_attestation, + ) + else: + result.notes.append( + "prompt-requirements oracle is a traceable candidate; independent reviews and " + "fixtures are pending" + ) + + +def _validate_gold_evidence_semantics(result: Result, evidence: dict) -> None: + if not evidence: + return + pages = [page.get("page") for page in evidence.get("canonical_export", {}).get("pages", [])] + result.require( + pages == list(range(1, 21)), + "gold evidence canonical-export pages must be sorted and exactly 1..20", + ) + tiers = [control.get("targeted_tier") for control in evidence.get("reference_controls", [])] + result.require( + sorted(tiers) == [1, 2, 3] and len(tiers) == 3, + "gold evidence reference controls must cover tiers exactly {1,2,3}", + ) + + +def _validate_release_evidence_instances( + result: Result, + oracle: dict, + gold_evidence: dict, +) -> tuple[dict, dict]: + assertion_inventory = _validate_json( + result, + "requirements/scored-assertion-inventory.json", + "scored-assertion-inventory.schema.json", + ) + _validate_scored_assertion_inventory(result, assertion_inventory, oracle) + _validate_json( + result, + "grader-source-tree-manifest.json", + "grader-source-tree-manifest.schema.json", + ) + environment_attestation = _validate_json( + result, + "environment-attestation.json", + "environment-attestation.schema.json", + ) + if environment_attestation: + try: + render_profiles = load_render_profiles(SCHEMAS) + expected_profile_hashes = environment_profile_hashes(SCHEMAS) + result.require( + environment_attestation.get("profile_hashes") == expected_profile_hashes, + "release mode: environment attestation profile hashes do not match normative files", + ) + result.require( + environment_attestation.get("export_contract") == render_profiles.export_contract(), + "release mode: environment attestation export contract differs from " + "normative profiles", + ) + except (OSError, ValueError) as error: + result.errors.append(f"release mode: render-profile reconstruction failed: {error}") + determinism_evidence = _validate_json( + result, + "export-determinism-evidence.json", + "export-determinism-evidence.schema.json", + ) + expected_determinism_bindings = { + "environment_attestation_sha256": ( + f"sha256:{hashlib.sha256(rfc8785.dumps(environment_attestation)).hexdigest()}" + ), + "original_gold_sha256": gold_evidence.get("original_authored_gold", {}).get("sha256"), + "resolved_gold_sha256": gold_evidence.get("resolved_gold", {}).get("sha256"), + "canonical_package_hash_profile_sha256": gold_evidence.get("profile_hashes", {}).get( + "canonical_package_hash_profile_sha256" + ), + "canonical_package_hash_v1": gold_evidence.get("canonical_package_hash_v1"), + "canonical_pdf_sha256": gold_evidence.get("canonical_export", {}).get("pdf_sha256"), + "canonical_png_sha256s": [ + page.get("png_sha256") + for page in gold_evidence.get("canonical_export", {}).get("pages", []) + ], + "export_profile_sha256": environment_attestation.get("profile_hashes", {}).get( + "export_profile_sha256" + ), + "ssim_profile_sha256": environment_attestation.get("profile_hashes", {}).get( + "ssim_profile_sha256" + ), + } + validate_export_determinism_evidence( + result, + determinism_evidence, + expected_bindings=expected_determinism_bindings, + ) + release_keys = ROOT / "RELEASE_KEYS.json" + _validate_path_against_schema(result, release_keys, SCHEMAS / "release-keys.schema.json") + + _validate_assertion_evidence_index(result, assertion_inventory) + mutations = sorted((BENCHMARK / "fixtures" / "mutations").glob("*.json")) + result.require(bool(mutations), "release mode: fixture mutation evidence is missing") + for mutation in mutations: + try: + json.loads(mutation.read_text(encoding="utf-8")) + except json.JSONDecodeError as error: + result.errors.append(f"{mutation}: {error}") + + scene_profile_sha256 = f"sha256:{_digest(SCHEMAS / 'scene-graph-profile-v1.json')}" + resolved_gold_sha256 = gold_evidence.get("resolved_gold", {}).get("sha256") + # Missing normative evidence is already reported by _validate_json. Do not compare + # dependent fixture bindings against None: that turns one absent root artifact into + # a misleading deck-plus-20-slides package-drift cascade. + if gold_evidence: + result.require( + gold_evidence.get("profile_hashes", {}).get("scene_graph_profile_sha256") + == scene_profile_sha256, + "release mode: gold evidence is bound to the wrong scene-graph profile", + ) + if environment_attestation: + result.require( + environment_attestation.get("profile_hashes", {}).get("scene_graph_profile_sha256") + == scene_profile_sha256, + "release mode: environment attestation is bound to the wrong scene-graph profile", + ) + deck_path = BENCHMARK / "fixtures" / "expected-deck.json" + deck_scene = _validate_path_against_schema( + result, + deck_path, + SCHEMAS / "scene-graph.schema.json", + ) + if deck_scene: + _validate_scene_graph_semantics( + result, + deck_scene, + expected_profile_sha256=scene_profile_sha256, + expected_package_sha256=resolved_gold_sha256, + expected_slides=list(range(1, 21)), + label="expected-deck.json", + ) + result.require( + deck_path.read_bytes() == rfc8785.dumps(deck_scene), + "release mode: expected-deck.json is not RFC 8785 JCS", + ) + if gold_evidence: + result.require( + gold_evidence.get("scene_graph_sha256") == f"sha256:{_digest(deck_path)}", + "release mode: gold evidence scene-graph hash does not match expected-deck.json", + ) + + scene_paths = [ + BENCHMARK / "fixtures" / "expected-scenegraphs" / f"slide-{slide:02d}.json" + for slide in range(1, 21) + ] + for slide, path in enumerate(scene_paths, 1): + data = _validate_path_against_schema(result, path, SCHEMAS / "scene-graph.schema.json") + if data: + _validate_scene_graph_semantics( + result, + data, + expected_profile_sha256=scene_profile_sha256, + expected_package_sha256=resolved_gold_sha256, + expected_slides=[slide], + label=path.name, + ) + if deck_scene: + expected_fixture = dict(deck_scene) | { + "slides": [deck_scene.get("slides", [])[slide - 1]] + } + result.require( + data == expected_fixture, + f"release mode: {path.name} is not the exact deck-graph slide projection", + ) + + baseline_names = { + "human-expert.json": "human_expert", + "programmatic-copy.json": "programmatic_copy", + "naive-llm.json": "naive_llm", + } + for name, kind in baseline_names.items(): + data = _validate_path_against_schema( + result, + BENCHMARK / "baselines" / name, + SCHEMAS / "baseline-evidence.schema.json", + ) + if data: + result.require( + data.get("baseline_kind") == kind, + f"release mode: {name} has the wrong baseline_kind", + ) + + result.require( + (BENCHMARK / "deck" / "gold" / "acidslide-v1-gold.pptx").is_file(), + "release mode: canonical gold deck is missing", + ) + exports = [BENCHMARK / "deck" / "exports" / f"slide-{slide:02d}.png" for slide in range(1, 21)] + result.require( + all(path.is_file() for path in exports), + "release mode: canonical slide-01..20 PNG exports are incomplete", + ) + return determinism_evidence, environment_attestation + + +def _validate_scene_graph_semantics( + result: Result, + scene_graph: dict, + *, + expected_profile_sha256: str, + expected_package_sha256: str | None, + expected_slides: list[int], + label: str, +) -> None: + result.require( + scene_graph.get("profile_sha256") == expected_profile_sha256, + f"release mode: {label} is bound to the wrong scene-graph profile", + ) + if expected_package_sha256 is not None: + result.require( + scene_graph.get("mce_resolved_package_sha256") == expected_package_sha256, + f"release mode: {label} is bound to the wrong resolved gold package", + ) + slides = scene_graph.get("slides", []) + result.require( + [slide.get("slide") for slide in slides if isinstance(slide, dict)] == expected_slides, + f"release mode: {label} has the wrong ordered slide set", + ) + seen_node_ids: set[str] = set() + + def validate_nodes( + nodes: object, + *, + slide: int, + source_part: object, + prefix: tuple[int, ...] = (), + parents: tuple[str, ...] = (), + ) -> None: + if not isinstance(nodes, list): + return + for index, node in enumerate(nodes): + if not isinstance(node, dict): + continue + structural_path = prefix + (index,) + expected_id = f"s{slide}:n" + ".".join(str(value) for value in structural_path) + node_id = node.get("node_id") + result.require( + node_id == expected_id and node.get("z_index") == index, + f"release mode: {label} has a non-normative node ID or z-index", + ) + result.require( + node.get("source_part") == source_part + and node.get("native_properties", {}).get("parent_group_path") == list(parents), + f"release mode: {label} has a node with the wrong source/group binding", + ) + result.require( + isinstance(node_id, str) and node_id not in seen_node_ids, + f"release mode: {label} has duplicate node IDs", + ) + if isinstance(node_id, str): + seen_node_ids.add(node_id) + validate_nodes( + node.get("children"), + slide=slide, + source_part=source_part, + prefix=structural_path, + parents=parents + (node_id,), + ) + + for slide in slides: + if not isinstance(slide, dict) or not isinstance(slide.get("slide"), int): + continue + relationships = slide.get("relationships", []) + result.require( + [item.get("id") for item in relationships if isinstance(item, dict)] + == sorted(item.get("id") for item in relationships if isinstance(item, dict)), + f"release mode: {label} relationships are not ordered by ID", + ) + validate_nodes( + slide.get("nodes"), + slide=slide["slide"], + source_part=slide.get("part_name"), + ) + + +def _checklist_documents() -> list[dict]: + paths = [BENCHMARK / "checklist" / "deck.yaml"] + sorted( + (BENCHMARK / "checklist" / "slides").glob("slide-*.yaml") + ) + documents: list[dict] = [] + for path in paths: + documents.extend( + document + for document in yaml.safe_load_all(path.read_text(encoding="utf-8")) + if isinstance(document, dict) + ) + return documents + + +def _reference_region_in_bounds(region: object) -> bool: + if not isinstance(region, dict): + return False + values = [region.get(key) for key in ("x", "y", "width", "height")] + if any(not isinstance(value, int) or isinstance(value, bool) for value in values): + return False + x, y, width, height = values + return ( + x >= 0 and y >= 0 and width > 0 and height > 0 and x + width <= 1920 and y + height <= 1080 + ) + + +def _validate_scored_assertion_inventory(result: Result, inventory: dict, oracle: dict) -> None: + if not inventory: + return + assertions = inventory.get("assertions", []) + result.require( + inventory.get("lifecycle_state") == "frozen", + "release mode: scored assertion inventory is not frozen", + ) + _validate_assertion_inventory_approvals(result, inventory) + result.require( + inventory.get("prompt_bundle_sha256") != "pending" + and inventory.get("reference_image_bundle_sha256") != "pending" + and inventory.get("asset_manifest_sha256") != "pending", + "release mode: scored assertion inventory contains pending bundle hashes", + ) + + checklist = _checklist_documents() + checklist_by_id = {document.get("id"): document for document in checklist} + assertions_by_item = { + assertion.get("checklist_item_id"): assertion + for assertion in assertions + if isinstance(assertion, dict) + } + result.require( + len(checklist) == 280 + and len(assertions) == 280 + and len(assertions_by_item) == 280 + and set(assertions_by_item) == set(checklist_by_id), + "release mode: assertion inventory must map exactly once to all 280 checklist items", + ) + not_frozen = sum( + assertion.get("lifecycle_state") != "frozen" + for assertion in assertions + if isinstance(assertion, dict) + ) + incomplete_provenance = sum( + assertion.get("provenance", {}).get("status") != "complete" + for assertion in assertions + if isinstance(assertion, dict) + ) + incomplete_evidence = sum( + assertion.get("evidence", {}).get("status") != "complete" + for assertion in assertions + if isinstance(assertion, dict) + ) + result.require( + not_frozen == 0, + f"release mode: {not_frozen} scored assertions are not frozen", + ) + result.require( + incomplete_provenance == 0, + f"release mode: {incomplete_provenance} scored assertion provenance records are incomplete", + ) + result.require( + incomplete_evidence == 0, + f"release mode: {incomplete_evidence} scored assertion evidence records are incomplete", + ) + + requirement_by_id = { + requirement.get("requirement_id"): requirement + for requirement in oracle.get("requirements", []) + if isinstance(requirement, dict) + } + sources_by_id = { + source.get("source_id"): source + for source in oracle.get("sources", []) + if isinstance(source, dict) + } + for checklist_id, assertion in assertions_by_item.items(): + item = checklist_by_id.get(checklist_id) + if not isinstance(item, dict) or not isinstance(assertion, dict): + continue + result.require( + assertion.get("assertion_id") == item.get("assertion_id") + and assertion.get("scope") == item.get("scope") + and assertion.get("slide") == item.get("slide") + and assertion.get("tier") == item.get("tier") + and assertion.get("statement") == item.get("description") + and assertion.get("source_of_truth") == item.get("source_of_truth"), + f"release mode: assertion/checklist identity mismatch for {checklist_id}", + ) + expected_method = item.get("verification", {}).get("method") + if expected_method == "hash_match": + expected_method = "embedded_media_hash" + result.require( + assertion.get("verification_method") == expected_method, + f"release mode: assertion/checklist verification mismatch for {checklist_id}", + ) + provenance = assertion.get("provenance", {}) + item_provenance = item.get("provenance", {}) + if provenance.get("status") != "complete" or item_provenance.get("status") != "complete": + continue + result.require( + provenance.get("kind") == item_provenance.get("kind") + and provenance.get("source_hash") == item_provenance.get("source_hash") + and provenance.get("locator") == item_provenance.get("locator"), + f"release mode: assertion/checklist provenance mismatch for {checklist_id}", + ) + if provenance.get("kind") == "prompt": + requirement_id = provenance.get("prompt_requirement_id") + requirement = requirement_by_id.get(requirement_id) + source = ( + sources_by_id.get(requirement.get("provenance", {}).get("source_id")) + if isinstance(requirement, dict) + else None + ) + result.require( + requirement is not None + and item.get("prompt_requirement_id") == requirement_id + and isinstance(source, dict) + and provenance.get("source_hash") == f"sha256:{source.get('sha256')}", + f"release mode: prompt provenance does not resolve for {checklist_id}", + ) + elif provenance.get("kind") == "reference_image": + item_reference = item_provenance.get("reference_image", {}) + result.require( + provenance.get("slide") == item_reference.get("slide") + and provenance.get("region") == item_reference.get("region") + and _reference_region_in_bounds(provenance.get("region")), + f"release mode: reference-image region is invalid for {checklist_id}", + ) + elif provenance.get("kind") == "asset_manifest": + result.require( + provenance.get("asset_id") == item_provenance.get("asset_id"), + f"release mode: asset provenance does not match for {checklist_id}", + ) + + +def _validate_assertion_evidence_index(result: Result, inventory: dict) -> None: + """Cross-bind every frozen assertion's evidence IDs to the release evidence index. + + A syntactically valid index alone is not evidence. It becomes part of the + release proof only when it is a one-to-one, exact projection of the frozen + assertion inventory's complete fixture and mutation identifiers. + """ + index_path = BENCHMARK / "fixtures" / "index.json" + result.require(index_path.is_file(), "release mode: fixtures/index.json is missing") + if not index_path.is_file() or not inventory: + return + try: + index = json.loads(index_path.read_text(encoding="utf-8")) + inventory_schema = json.loads( + (SCHEMAS / "scored-assertion-inventory.schema.json").read_text(encoding="utf-8") + ) + index_schema = { + "$ref": f"{inventory_schema['$id']}#/$defs/assertion_evidence_index" + } + errors = sorted(_validator(index_schema).iter_errors(index), key=str) + for error in errors: + result.errors.append(f"fixtures/index.json: schema: {error.message}") + except (KeyError, json.JSONDecodeError, jsonschema.SchemaError) as error: + result.errors.append(f"fixtures/index.json: {error}") + return + if not isinstance(index, dict): + return + + result.require( + index.get("assertion_inventory_review_sha256") + == _validate_assertion_inventory_projection_sha256(inventory), + "release mode: fixtures/index.json is bound to the wrong frozen assertion inventory", + ) + expected: dict[str, tuple[object, object, object, object]] = {} + for assertion in inventory.get("assertions", []): + if not isinstance(assertion, dict): + continue + evidence = assertion.get("evidence", {}) + assertion_id = assertion.get("assertion_id") + if not isinstance(assertion_id, str) or not isinstance(evidence, dict): + continue + expected[assertion_id] = ( + assertion.get("checklist_item_id"), + evidence.get("positive_fixture_ids"), + evidence.get("single_fault_negative_fixture_ids"), + evidence.get("mutation_expectation_ids"), + ) + actual: dict[str, tuple[object, object, object, object]] = {} + for entry in index.get("assertions", []): + if not isinstance(entry, dict): + continue + assertion_id = entry.get("assertion_id") + if not isinstance(assertion_id, str): + continue + actual[assertion_id] = ( + entry.get("checklist_item_id"), + entry.get("positive_fixture_ids"), + entry.get("single_fault_negative_fixture_ids"), + entry.get("mutation_expectation_ids"), + ) + result.require( + len(actual) == len(index.get("assertions", [])) + and set(actual) == set(expected) + and actual == expected, + "release mode: fixtures/index.json does not exactly cross-bind all frozen " + "assertion evidence IDs", + ) + + +def _validate_assertion_inventory_projection_sha256(inventory: dict) -> str: + projection = { + "domain": "AcidSlide scored assertion inventory review v1", + "inventory": {key: value for key, value in inventory.items() if key != "review"}, + } + return f"sha256:{hashlib.sha256(rfc8785.dumps(projection)).hexdigest()}" + + +def _validate_path_against_schema(result: Result, data_path: Path, schema_path: Path) -> dict: + result.require(data_path.is_file(), f"release mode: normative artifact missing: {data_path}") + result.require(schema_path.is_file(), f"normative schema missing: {schema_path}") + if not data_path.is_file() or not schema_path.is_file(): + return {} + try: + data = json.loads(data_path.read_text(encoding="utf-8")) + schema = json.loads(schema_path.read_text(encoding="utf-8")) + errors = sorted(_validator(schema).iter_errors(data), key=str) + for error in errors: + result.errors.append(f"{data_path.name}: schema: {error.message}") + return data + except (json.JSONDecodeError, jsonschema.SchemaError) as error: + result.errors.append(f"{data_path.name}: {error}") + return {} + + +def _parse_timestamp(value: object, field: str) -> datetime: + if not isinstance(value, str): + raise ValueError(f"{field} must be an RFC 3339 timestamp") + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError as error: + raise ValueError(f"{field} is not a valid RFC 3339 timestamp") from error + if parsed.tzinfo is None: + raise ValueError(f"{field} must include a UTC offset") + return parsed.astimezone(UTC) + + +def _release_index_hash(index: dict) -> str: + import rfc8785 + + return f"sha256:{hashlib.sha256(rfc8785.dumps(index)).hexdigest()}" + + +def _verify_release_index_signature(index: dict, release_keys: dict) -> None: + import rfc8785 + from cryptography.exceptions import InvalidSignature + from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey + + issued_at = _parse_timestamp(index.get("issued_at"), "issued_at") + effective_at = _parse_timestamp(index.get("effective_at"), "effective_at") + keys_by_id = { + key.get("key_id"): key for key in release_keys.get("keys", []) if isinstance(key, dict) + } + if len(keys_by_id) != len(release_keys.get("keys", [])): + raise ValueError("RELEASE_KEYS.json contains duplicate or invalid key IDs") + + signed_payload = dict(index) + signatures = signed_payload.pop("signatures", None) + if not isinstance(signatures, list) or not signatures: + raise ValueError("release index contains no signatures") + message = rfc8785.dumps(signed_payload) + verified_key_ids: set[str] = set() + failures: list[str] = [] + for signature in signatures: + if not isinstance(signature, dict): + failures.append("malformed signature entry") + continue + key_id = signature.get("key_id") + key = keys_by_id.get(key_id) + if key is None: + failures.append(f"unknown key {key_id!r}") + continue + if key.get("algorithm") != "Ed25519" or signature.get("algorithm") != "Ed25519": + failures.append(f"key {key_id!r} uses the wrong algorithm") + continue + try: + valid_from = _parse_timestamp(key.get("valid_from"), f"key {key_id} valid_from") + valid_until = ( + _parse_timestamp(key["valid_until"], f"key {key_id} valid_until") + if key.get("valid_until") is not None + else None + ) + revoked_at = ( + _parse_timestamp(key["revoked_at"], f"key {key_id} revoked_at") + if key.get("revoked_at") is not None + else None + ) + if issued_at < valid_from or effective_at < valid_from: + raise ValueError("key was not yet valid") + if valid_until is not None and (issued_at > valid_until or effective_at > valid_until): + raise ValueError("key validity had expired") + if revoked_at is not None and (issued_at >= revoked_at or effective_at >= revoked_at): + raise ValueError("key was revoked") + public_bytes = b64decode(key["public_key_base64"], validate=True) + signature_bytes = b64decode(signature["signature_base64"], validate=True) + if len(public_bytes) != 32 or len(signature_bytes) != 64: + raise ValueError("key or signature has the wrong byte length") + Ed25519PublicKey.from_public_bytes(public_bytes).verify(signature_bytes, message) + verified_key_ids.add(str(key_id)) + except ( + Base64Error, + InvalidSignature, + KeyError, + TypeError, + ValueError, + ) as error: + failures.append(f"key {key_id!r}: {error}") + if not verified_key_ids: + details = "; ".join(failures) if failures else "no authorized signature" + raise ValueError(f"release index has no valid authorized signature: {details}") + + +def verify_release_chain( + indexes: list[dict], + release_keys: dict, + *, + trusted_genesis_sha256: str | None = None, + persisted_head: tuple[str, int, str] | None = None, + now: datetime | None = None, + clock_skew_seconds: int = 300, +) -> tuple[str, int, str]: + """Verify a complete signed chain and return its durable highest head. + + ``persisted_head`` is the previously accepted ``(channel, sequence, hash)``. + Supplying it makes rollback and same-sequence fork checks survive process + restarts; a caller must persist the returned tuple before activation. + """ + + if not indexes: + raise ValueError("release index chain is empty") + moment = (now or datetime.now(UTC)).astimezone(UTC) + previous: dict | None = None + previous_hash: str | None = None + previous_issued: datetime | None = None + previous_effective: datetime | None = None + state_order = {"active": 0, "frozen": 1, "superseded": 2} + seen_sequences: set[int] = set() + seen_hashes: dict[int, str] = {} + + for position, index in enumerate(indexes): + if not isinstance(index, dict): + raise ValueError("release index chain contains a non-object") + channel = index.get("channel") + sequence = index.get("sequence") + state = index.get("state") + if channel != "acidslide-v1-stable": + raise ValueError("release index channel is not acidslide-v1-stable") + if not isinstance(sequence, int) or isinstance(sequence, bool) or sequence < 1: + raise ValueError("release index sequence is invalid") + if sequence in seen_sequences: + raise ValueError("release index chain contains a duplicate sequence or fork") + if state not in state_order: + raise ValueError("release index state is invalid") + + issued_at = _parse_timestamp(index.get("issued_at"), "issued_at") + effective_at = _parse_timestamp(index.get("effective_at"), "effective_at") + if effective_at < issued_at: + raise ValueError("release index effective_at precedes issued_at") + if issued_at > moment + timedelta(seconds=clock_skew_seconds): + raise ValueError("release index was issued outside the allowed clock-skew bound") + if effective_at > moment: + raise ValueError("release index is not yet effective") + + current_hash = _release_index_hash(index) + if position == 0: + if sequence != 1 or index.get("previous_release_index_sha256") is not None: + raise ValueError("release chain does not begin at trusted sequence 1 genesis") + if trusted_genesis_sha256 is not None and current_hash != trusted_genesis_sha256: + raise ValueError("release genesis does not match the configured trust anchor") + else: + assert previous is not None and previous_hash is not None + if sequence != previous["sequence"] + 1: + raise ValueError("release index chain contains a sequence gap or rollback") + if index.get("previous_release_index_sha256") != previous_hash: + raise ValueError("release index chain contains an unknown fork") + if previous_issued is not None and issued_at < previous_issued: + raise ValueError("release index issued_at moved backward") + if previous_effective is not None and effective_at < previous_effective: + raise ValueError("release index effective_at moved backward") + if state_order[state] < state_order[previous["state"]]: + raise ValueError("release index state moved backward") + + _verify_release_index_signature(index, release_keys) + seen_sequences.add(sequence) + seen_hashes[sequence] = current_hash + previous = index + previous_hash = current_hash + previous_issued = issued_at + previous_effective = effective_at + + assert previous is not None and previous_hash is not None + head = (str(previous["channel"]), int(previous["sequence"]), previous_hash) + if persisted_head is not None: + persisted_channel, persisted_sequence, persisted_hash = persisted_head + if persisted_channel != head[0]: + raise ValueError("persisted release head belongs to another channel") + if head[1] < persisted_sequence: + raise ValueError("release chain attempts rollback below the persisted head") + accepted_hash = seen_hashes.get(persisted_sequence) + if accepted_hash != persisted_hash: + raise ValueError("release chain does not contain the persisted trusted head") + return head + + +def _validate_oracle(result: Result, oracle: dict) -> None: + sources = {source.get("source_id"): source for source in oracle.get("sources", [])} + requirements = oracle.get("requirements", []) + ids = [item.get("requirement_id") for item in requirements] + result.require(len(ids) == len(set(ids)), "prompt requirements contain duplicate IDs") + slide_counts = {number: 0 for number in range(1, 21)} + deck_count = 0 + for source in sources.values(): + path = ROOT / source.get("path", "") + result.require(path.is_file(), f"oracle source is missing: {path}") + if path.is_file(): + result.require( + _digest(path) == source.get("sha256"), + f"oracle source hash drift: {path}", + ) + for item in requirements: + if item.get("scope") == "deck": + deck_count += 1 + elif item.get("slide") in slide_counts: + slide_counts[item["slide"]] += 1 + provenance = item.get("provenance", {}) + source = sources.get(provenance.get("source_id")) + if source is None: + result.errors.append(f"{item.get('requirement_id')}: unknown source_id") + continue + path = ROOT / source["path"] + if not path.is_file(): + continue + lines = path.read_text(encoding="utf-8").splitlines() + start = provenance.get("line_start", 0) + end = provenance.get("line_end", 0) + if not (1 <= start <= end <= len(lines)): + result.errors.append(f"{item.get('requirement_id')}: invalid source line range") + continue + excerpt = "\n".join(lines[start - 1 : end]) + result.require( + excerpt == provenance.get("excerpt"), + f"{item.get('requirement_id')}: excerpt drift", + ) + result.require( + hashlib.sha256(excerpt.encode("utf-8")).hexdigest() == provenance.get("excerpt_sha256"), + f"{item.get('requirement_id')}: excerpt hash drift", + ) + result.require(deck_count > 0, "prompt requirements contain no deck assertions") + for slide, count in slide_counts.items(): + result.require( + count > 0, + f"prompt requirements contain no assertions for slide {slide:02d}", + ) + result.notes.append( + f"prompt-requirements inventory: {deck_count} deck + " + f"{sum(slide_counts.values())} slide clauses" + ) + + +def _validate_frozen_release_files( + result: Result, + gold_evidence: dict, + determinism_evidence: dict, + environment_attestation: dict, +) -> None: + manifest = BENCHMARK / "scoring-manifest.json" + release_index = BENCHMARK / "release-index.json" + release_chain = BENCHMARK / "release-index-chain.json" + result.require(manifest.is_file(), "release mode: scoring-manifest.json is missing") + result.require(release_index.is_file(), "release mode: release-index.json is missing") + if not manifest.is_file() or not release_index.is_file(): + return + try: + import rfc8785 + except ImportError: + result.errors.append("release mode: rfc8785 is unavailable for JCS verification") + return + manifest_data = json.loads(manifest.read_text(encoding="utf-8")) + index_data = json.loads(release_index.read_text(encoding="utf-8")) + _validate_path_against_schema(result, manifest, SCHEMAS / "scoring-manifest.schema.json") + _validate_path_against_schema(result, release_index, SCHEMAS / "release-index.schema.json") + indexes = [index_data] + if release_chain.is_file(): + chain_data = _validate_path_against_schema( + result, + release_chain, + SCHEMAS / "release-index-chain.schema.json", + ) + result.require( + release_chain.read_bytes() == rfc8785.dumps(chain_data), + "release index chain is not RFC 8785 JCS", + ) + chain_indexes = chain_data.get("indexes", []) + if isinstance(chain_indexes, list) and chain_indexes: + indexes = chain_indexes + result.require( + rfc8785.dumps(chain_indexes[-1]) == release_index.read_bytes(), + "release-index.json does not equal the packaged release-chain head", + ) + else: + result.require( + index_data.get("sequence") == 1, + "release mode: release-index-chain.json is required above sequence 1", + ) + release_keys_path = ROOT / "RELEASE_KEYS.json" + release_keys = _validate_path_against_schema( + result, release_keys_path, SCHEMAS / "release-keys.schema.json" + ) + if release_keys: + try: + channel, sequence, head_hash = verify_release_chain(indexes, release_keys) + result.notes.append( + "verified signed release chain head: " + f"channel={channel}, sequence={sequence}, hash={head_hash}" + ) + except (ImportError, ValueError) as error: + result.errors.append(f"release mode: release-index signature/chain: {error}") + result.require( + index_data.get("state") == "active", + "release mode: release-index chain head is not active", + ) + result.require( + manifest.read_bytes() == rfc8785.dumps(manifest_data), + "scoring manifest is not RFC 8785 JCS", + ) + result.require( + release_index.read_bytes() == rfc8785.dumps(index_data), + "release index is not RFC 8785 JCS", + ) + determinism_path = BENCHMARK / "export-determinism-evidence.json" + if determinism_evidence and determinism_path.is_file(): + result.require( + determinism_path.read_bytes() == rfc8785.dumps(determinism_evidence), + "export determinism evidence is not RFC 8785 JCS", + ) + descriptor = index_data.get("cohort_descriptor", {}) + expected_manifest = f"sha256:{_digest(manifest)}" + expected_cohort = f"sha256:{hashlib.sha256(rfc8785.dumps(descriptor)).hexdigest()}" + result.require( + index_data.get("scoring_manifest_sha256") == expected_manifest + and descriptor.get("scoring_manifest_sha256") == expected_manifest, + "release index scoring-manifest hash mismatch", + ) + result.require( + index_data.get("scoring_cohort_id") == expected_cohort, + "release index cohort ID mismatch", + ) + if environment_attestation: + environment_sha256 = ( + f"sha256:{hashlib.sha256(rfc8785.dumps(environment_attestation)).hexdigest()}" + ) + runtime = manifest_data.get("runtime", {}) + attested_versions = environment_attestation.get("runtime_versions", {}) + attested_fonts = environment_attestation.get("font_environment", {}) + attested_binaries = { + record.get("name"): record + for record in environment_attestation.get("binary_inventory", []) + if isinstance(record, dict) + } + result.require( + runtime.get("environment_attestation_sha256") == environment_sha256 + and descriptor.get("environment_attestation_sha256") == environment_sha256, + "scoring manifest/release index environment-attestation hash mismatch", + ) + result.require( + manifest_data.get("platform") == environment_attestation.get("platform") + and manifest_data.get("oci_image_digest") + == environment_attestation.get("oci_image_digest"), + "scoring manifest platform/OCI digest differs from environment attestation", + ) + version_fields = ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + ) + result.require( + all(runtime.get(field) == attested_versions.get(field) for field in version_fields), + "scoring manifest runtime versions differ from environment attestation", + ) + result.require( + runtime.get("fontconfig_config_sha256") + == attested_fonts.get("fontconfig_config_sha256") + and runtime.get("libfaketime_library_sha256") + == attested_binaries.get("libfaketime", {}).get("sha256"), + "scoring manifest runtime file hashes differ from environment attestation", + ) + try: + render_profiles = load_render_profiles(SCHEMAS) + result.require( + manifest_data.get("render_profiles") + == render_profiles.hashes + == { + key: environment_attestation.get("profile_hashes", {}).get(key) + for key in render_profiles.hashes + }, + "scoring manifest render-profile hashes are stale or substituted", + ) + result.require( + manifest_data.get("export") == render_profiles.scoring_export() + and manifest_data.get("visual_comparison") + == render_profiles.scoring_visual_comparison(), + "scoring manifest render/SSIM projections differ from normative profiles", + ) + except (OSError, ValueError) as error: + result.errors.append(f"release mode: render-profile binding failed: {error}") + result.require( + manifest_data.get("artifacts", {}).get("grader_source_tree_sha256") + == environment_attestation.get("grader_source_tree_sha256"), + "scoring manifest grader source-tree differs from environment attestation", + ) + if gold_evidence: + gold = manifest_data.get("gold", {}) + export = gold_evidence.get("canonical_export", {}) + resolved = gold_evidence.get("resolved_gold", {}) + result.require( + gold.get("original_byte_sha256") + == gold_evidence.get("original_authored_gold", {}).get("sha256"), + "scoring manifest original gold hash does not match gold evidence", + ) + result.require( + gold.get("mce_resolved_package_sha256") == resolved.get("sha256") + and gold.get("mce_resolved_package_size_bytes") == resolved.get("size_bytes"), + "scoring manifest resolved gold identity does not match gold evidence", + ) + result.require( + gold.get("canonical_package_hash_profile_sha256") + == gold_evidence.get("profile_hashes", {}).get("canonical_package_hash_profile_sha256") + and gold.get("canonical_package_hash_v1") + == gold_evidence.get("canonical_package_hash_v1"), + "scoring manifest canonical gold identity does not match gold evidence", + ) + result.require( + manifest_data.get("structural_profiles", {}).get("scene_graph_profile_sha256") + == gold_evidence.get("profile_hashes", {}).get("scene_graph_profile_sha256") + and gold.get("scene_graph_sha256") == gold_evidence.get("scene_graph_sha256"), + "scoring manifest scene-graph profile/hash does not match gold evidence", + ) + result.require( + gold.get("canonical_pdf_sha256") == export.get("pdf_sha256"), + "scoring manifest canonical PDF hash does not match gold evidence", + ) + result.require( + gold.get("canonical_png_sha256s") + == [page.get("png_sha256") for page in export.get("pages", [])], + "scoring manifest canonical PNG hashes/order do not match gold evidence", + ) + if determinism_evidence and determinism_path.is_file(): + result.require( + gold.get("export_determinism_evidence_sha256") + == f"sha256:{_digest(determinism_path)}", + "scoring manifest does not bind the export determinism evidence", + ) diff --git a/acidslide-v1/grader/README.md b/acidslide-v1/grader/README.md index b23b24f..93933b3 100644 --- a/acidslide-v1/grader/README.md +++ b/acidslide-v1/grader/README.md @@ -1,5 +1,48 @@ # AcidSlide Grader -ECMA-376 slide generation fidelity benchmark grader. +The AcidSlide CLI performs quarantine checks, deterministic ECMA-376 Markup Compatibility preprocessing, Part 1 Transitional XSD validation, LibreOffice export, SSIM comparison, native object inspection, checklist evaluation, and report generation. -See `ACIDSLIDE_OPENSPEC.md` in the repository root for the full specification. +The wheel contains the benchmark corpus and schemas. Source and Docker layouts are also discovered automatically; `--benchmark-dir` or `ACIDSLIDE_BENCHMARK_DIR` can select an explicit corpus. + +```bash +uv sync --extra dev --locked +uv run acidslide validate ../benchmark/deck/gold/acidslide-v1-gold.pptx +uv run acidslide grade ../submission.pptx --tier 3 \ + --artifact-context ./local-artifact-context.json --format json +uv run acidslide grade ../submission.pptx --tier 3 \ + --artifact-context ./local-artifact-context.json --format html -o report.html +``` + +Output formats are `text`, `json`, and standalone `html`. Use `--artifacts DIR` to retain `diff-slide-NN.png` visual diagnostics. Incomplete verification exits with status `2` and is always reported as `eligible: false`. + +`--artifact-context` is required and must name a complete JSON serialization of +`ArtifactReportContext`, including explicit `null` values. Missing or unknown fields are rejected. The +CLI never invents release, artifact, gold, profile, generation, or environment identities; it verifies +the supplied artifact hashes and the RFC 8785 environment-attestation hash against the signed scoring +cohort before grading. + +Local scores are self-reported. Only the controlled hosted service may label a grading result grading-verified; generation metadata remains generation-attested. + +Frozen releases above sequence 1 include canonical `benchmark/release-index-chain.json`. Configure +the independently published genesis checkpoint and a durable, non-cache acceptance-state path before +grading: + +```bash +export ACIDSLIDE_TRUSTED_GENESIS_SHA256='sha256:' +export ACIDSLIDE_RELEASE_STATE_PATH='/var/lib/acidslide/release-head-v1.json' +export ACIDSLIDE_GRADER_SOURCE_PATH='/opt/acidslide/grader-source-tree.tar' +``` + +The verifier checks every index signature, sequence, predecessor hash, cohort binding, and effective +time from genesis through the packaged head, then atomically persists the highest accepted head +before returning it. A lower sequence, same-sequence alternate, fork, gap, premature head, or chain +whose final entry differs from `release-index.json` fails closed. Sequence-1 packages remain +supported; production deployments should still pin their published genesis explicitly. + +Before accepting that head, the verifier also reconstructs the complete grader source inventory from +the repository `grader/` directory, packaged `benchmark/grader-source-tree.tar`, or the explicit +`ACIDSLIDE_GRADER_SOURCE_PATH`. It requires exact file membership, byte length, SHA-256, and execute +bits to match the canonical `grader-source-tree-manifest.json` and all signed scoring-manifest/cohort +bindings. Links, special files, path collisions, extras, omissions, and archive traversal fail closed. + +See `ACIDSLIDE_OPENSPEC.md` in the repository root for the normative contract. diff --git a/acidslide-v1/grader/acidslide/affected_slides.py b/acidslide-v1/grader/acidslide/affected_slides.py new file mode 100644 index 0000000..4899928 --- /dev/null +++ b/acidslide-v1/grader/acidslide/affected_slides.py @@ -0,0 +1,122 @@ +"""Content-addressed affected-slide selectors for deck-scoped automatic failures.""" + +from __future__ import annotations + +import hashlib +import json +from functools import lru_cache +from typing import TYPE_CHECKING, Any + +import rfc8785 + +from acidslide.resources import resolve_benchmark_dir + +if TYPE_CHECKING: + from pathlib import Path + + from acidslide.inspect_ooxml import DeckGraph, SceneObject + +SELECTOR_REGISTRY = "requirements/affected-slide-selectors-v1.json" +NON_BUNDLED_FONT_SELECTOR = "acidslide.affected-slides.non-bundled-font.v1" +NOTES_COMMENTS_SELECTOR = "acidslide.affected-slides.notes-comments.v1" + + +class AffectedSlideSelectorError(ValueError): + """Raised when a named selector is missing, altered, or unsupported.""" + + +def selector_binding(selector_id: str, registry_path: Path | None = None) -> dict[str, str]: + """Return the verified identifier/hash binding for one selector.""" + registry = _load_registry(str(registry_path) if registry_path is not None else "") + try: + entry = registry[selector_id] + except KeyError as exc: + raise AffectedSlideSelectorError(f"Unknown affected-slide selector: {selector_id}") from exc + return { + "selector_id": selector_id, + "selector_sha256": entry["selector_sha256"], + } + + +def resolve_named_selector( + selector_id: str, + selector_sha256: str, + deck: DeckGraph, + bundled_fonts: set[str], + registry_path: Path | None = None, +) -> list[int]: + """Verify and execute one frozen named selector against a deck graph.""" + binding = selector_binding(selector_id, registry_path) + if binding["selector_sha256"] != selector_sha256: + raise AffectedSlideSelectorError( + f"Affected-slide selector hash mismatch for {selector_id}: " + f"expected {binding['selector_sha256']}, got {selector_sha256}" + ) + if selector_id == NON_BUNDLED_FONT_SELECTOR: + return _non_bundled_font_slides(deck, bundled_fonts) + if selector_id == NOTES_COMMENTS_SELECTOR: + return _notes_or_comment_slides(deck) + raise AffectedSlideSelectorError(f"Unsupported affected-slide selector: {selector_id}") + + +@lru_cache(maxsize=4) +def _load_registry(registry_path: str) -> dict[str, dict[str, Any]]: + path = ( + resolve_benchmark_dir() / SELECTOR_REGISTRY + if not registry_path + else _path_from_string(registry_path) + ) + document = json.loads(path.read_text(encoding="utf-8")) + if document.get("registry_id") != "acidslide-affected-slide-selectors-v1": + raise AffectedSlideSelectorError(f"Unsupported affected-slide selector registry: {path}") + + result: dict[str, dict[str, Any]] = {} + for entry in document.get("selectors", []): + selector_id = entry.get("selector_id") + descriptor = entry.get("descriptor") + claimed_hash = entry.get("selector_sha256") + if not isinstance(selector_id, str) or not isinstance(descriptor, dict): + raise AffectedSlideSelectorError(f"Malformed selector entry in {path}") + actual_hash = f"sha256:{hashlib.sha256(rfc8785.dumps(descriptor)).hexdigest()}" + if claimed_hash != actual_hash: + raise AffectedSlideSelectorError( + f"Affected-slide selector descriptor hash mismatch for {selector_id}" + ) + if descriptor.get("selector_id") != selector_id or selector_id in result: + raise AffectedSlideSelectorError(f"Invalid selector identity in {path}: {selector_id}") + result[selector_id] = entry + if not result: + raise AffectedSlideSelectorError(f"Affected-slide selector registry is empty: {path}") + return result + + +def _path_from_string(value: str) -> Path: + from pathlib import Path + + return Path(value) + + +def _non_bundled_font_slides(deck: DeckGraph, bundled_fonts: set[str]) -> list[int]: + affected: list[int] = [] + for slide in deck.slides: + if any( + run.font_family + and not run.font_family.startswith("+") + and run.font_family.lower() not in bundled_fonts + for obj in _collect_objects_recursive(slide.objects) + for run in obj.text_runs + ): + affected.append(slide.slide_number) + return sorted(set(affected)) + + +def _notes_or_comment_slides(deck: DeckGraph) -> list[int]: + return sorted(deck.notes_slides | deck.comment_slides) + + +def _collect_objects_recursive(objects: list[SceneObject]) -> list[SceneObject]: + result: list[SceneObject] = [] + for obj in objects: + result.append(obj) + result.extend(_collect_objects_recursive(obj.children)) + return result diff --git a/acidslide-v1/grader/acidslide/checklist.py b/acidslide-v1/grader/acidslide/checklist.py index 91458f3..33c2278 100644 --- a/acidslide-v1/grader/acidslide/checklist.py +++ b/acidslide-v1/grader/acidslide/checklist.py @@ -4,11 +4,13 @@ import json from dataclasses import dataclass, field -from pathlib import Path -from typing import Any +from typing import TYPE_CHECKING, Any import yaml # type: ignore[import-untyped] +if TYPE_CHECKING: + from pathlib import Path + SEVERITY_WEIGHTS: dict[str, int] = { "critical": 3, "major": 2, @@ -30,6 +32,7 @@ class Verification: class FailureMode: automatic_fail_if: list[str] = field(default_factory=list) propagation: str = "zero_item" + affected_slides: dict[str, Any] = field(default_factory=dict) @dataclass @@ -48,6 +51,7 @@ class ChecklistItem: verification: Verification failure_mode: FailureMode = field(default_factory=FailureMode) slide: int | None = None + assertion_id: str = "" @property def weight(self) -> int: @@ -113,6 +117,7 @@ def _parse_item(raw: dict[str, Any], source_path: Path) -> ChecklistItem: failure_mode = FailureMode( automatic_fail_if=failure_raw.get("automatic_fail_if", []), propagation=failure_raw.get("propagation", "zero_item"), + affected_slides=failure_raw.get("affected_slides", {}), ) return ChecklistItem( @@ -128,13 +133,14 @@ def _parse_item(raw: dict[str, Any], source_path: Path) -> ChecklistItem: verification=verification, failure_mode=failure_mode, slide=raw.get("slide"), + assertion_id=raw.get("assertion_id", ""), ) def validate_checklist_schema(checklist_dir: Path, schema_path: Path) -> list[str]: """Validate all YAML files against the JSON schema. Returns list of errors.""" try: - import jsonschema # type: ignore[import-untyped] + import jsonschema except ImportError: return ["jsonschema not installed — skipping schema validation"] diff --git a/acidslide-v1/grader/acidslide/cli.py b/acidslide-v1/grader/acidslide/cli.py index a206deb..373ce04 100644 --- a/acidslide-v1/grader/acidslide/cli.py +++ b/acidslide-v1/grader/acidslide/cli.py @@ -1,6 +1,8 @@ """AcidSlide CLI — benchmark grading tool.""" +import json from pathlib import Path +from typing import Any import click from rich.console import Console @@ -16,6 +18,168 @@ def main() -> None: """AcidSlide benchmark grader — ECMA-376 slide generation fidelity testing.""" +@main.command("build-environment-candidate") +@click.option( + "--oci-image-digest", + required=True, + help="RepoDigest verified outside the network-isolated candidate container", +) +@click.option( + "--attested-at", + required=True, + help="Explicit RFC 3339 UTC timestamp; never inferred from the frozen runtime clock", +) +@click.option("--canary-id", required=True, help="Stable identifier for the real canary pair") +@click.option( + "--canary-input", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + required=True, + help="Exact canary input bytes", +) +@click.option( + "--canary-report", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + required=True, + help="Exact score-semantic canary report bytes", +) +@click.option( + "--schema-dir", + type=click.Path(exists=True, file_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/schemas"), + show_default=True, +) +@click.option( + "--font-manifest", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/benchmark/fonts/manifest.json"), + show_default=True, +) +@click.option( + "--dockerfile", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/build/Dockerfile"), + show_default=True, +) +@click.option( + "--grader-lockfile", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/grader/uv.lock"), + show_default=True, +) +@click.option( + "--grader-root", + type=click.Path(exists=True, file_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/grader"), + show_default=True, +) +def build_environment_candidate( + oci_image_digest: str, + attested_at: str, + canary_id: str, + canary_input: Path, + canary_report: Path, + schema_dir: Path, + font_manifest: Path, + dockerfile: Path, + grader_lockfile: Path, + grader_root: Path, +) -> None: + """Reconstruct a non-final candidate from a network-isolated linux/amd64 image.""" + import rfc8785 + + from acidslide.environment import ( + EnvironmentAttestationError, + construct_environment_attestation_candidate, + environment_attestation_sha256, + runtime_freeze_input, + ) + + try: + payload, source_manifest = construct_environment_attestation_candidate( + oci_image_digest=oci_image_digest, + attested_at=attested_at, + canary_id=canary_id, + canary_input_path=canary_input, + canary_report_path=canary_report, + schema_dir=schema_dir, + font_manifest_path=font_manifest, + dockerfile_path=dockerfile, + grader_lockfile_path=grader_lockfile, + grader_root=grader_root, + ) + envelope: dict[str, Any] = { + "candidate": True, + "environment_attestation": payload, + "environment_attestation_sha256": environment_attestation_sha256(payload), + "grader_source_tree_manifest": source_manifest, + "runtime_freeze_input": runtime_freeze_input(payload), + } + except (OSError, ValueError, EnvironmentAttestationError) as exc: + console.print(f"[red]Environment candidate failed:[/red] {exc}") + raise click.exceptions.Exit(2) from exc + click.echo(rfc8785.dumps(envelope).decode("utf-8")) + + +@main.command("attest-environment") +@click.option( + "--expected-json", + required=True, + help="Frozen schema-valid environment attestation JSON", +) +@click.option( + "--oci-image-digest", + required=True, + help="RepoDigest verified by the worker before starting this container", +) +@click.option( + "--schema", + "schema_path", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=None, + help="Explicit environment-attestation schema", +) +@click.option( + "--font-manifest", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=Path("/opt/acidslide/benchmark/fonts/manifest.json"), + show_default=True, + help="Exact font manifest installed in the grader image", +) +def attest_environment( + expected_json: str, + oci_image_digest: str, + schema_path: Path | None, + font_manifest: Path, +) -> None: + """Reconstruct and verify the frozen attestation inside the live container.""" + import rfc8785 + + from acidslide.environment import ( + EnvironmentAttestationError, + environment_attestation_sha256, + reconstruct_environment_attestation, + ) + + try: + expected = json.loads(expected_json) + if not isinstance(expected, dict): + raise EnvironmentAttestationError("Expected environment attestation must be an object") + payload = reconstruct_environment_attestation( + expected, + oci_image_digest=oci_image_digest, + schema_path=schema_path, + font_manifest_path=font_manifest, + ) + envelope: dict[str, Any] = { + "environment_attestation": payload, + "environment_attestation_sha256": environment_attestation_sha256(payload), + } + except (json.JSONDecodeError, OSError, EnvironmentAttestationError) as exc: + console.print(f"[red]Environment attestation failed:[/red] {exc}") + raise click.exceptions.Exit(2) from exc + click.echo(rfc8785.dumps(envelope).decode("utf-8")) + + @main.command() @click.argument("submission", type=click.Path(exists=True, path_type=Path)) @click.option("--tier", type=click.Choice(["1", "2", "3"]), required=True, help="Difficulty tier") @@ -26,29 +190,83 @@ def main() -> None: help="Path to benchmark data directory", ) @click.option("--output", "-o", type=click.Path(path_type=Path), default=None, help="Report output") -@click.option("--format", "fmt", type=click.Choice(["json", "html"]), default="json") +@click.option( + "--artifacts", + type=click.Path(path_type=Path), + default=None, + help="Directory for private visual diff artifacts", +) +@click.option( + "--artifact-context", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + required=True, + help="Complete caller-supplied ArtifactReportContext JSON", +) +@click.option( + "--format", + "fmt", + type=click.Choice(["text", "json", "html"]), + default="text", + show_default=True, + help="Report serialization for stdout or --output", +) def grade( submission: Path, tier: str, benchmark_dir: Path | None, output: Path | None, + artifacts: Path | None, + artifact_context: Path, fmt: str, ) -> None: """Grade a .pptx submission against the AcidSlide benchmark.""" + from acidslide.models import ArtifactReportContext from acidslide.pipeline import run_pipeline + from acidslide.provenance import ReleaseProvenanceError + from acidslide.resources import BenchmarkDataError - result = run_pipeline( - submission=submission, - tier=int(tier), - benchmark_dir=benchmark_dir, - output_format=fmt, - ) + try: + raw_context: Any = json.loads(artifact_context.read_text(encoding="utf-8")) + if not isinstance(raw_context, dict): + raise ValueError("artifact report context must be a JSON object") + context = ArtifactReportContext.from_dict(raw_context) + except (OSError, json.JSONDecodeError, TypeError, ValueError) as exc: + raise click.BadParameter(str(exc), param_hint="--artifact-context") from exc + + try: + result = run_pipeline( + submission=submission, + tier=int(tier), + benchmark_dir=benchmark_dir, + output_format=fmt, + artifact_dir=artifacts, + artifact_context=context, + ) + except (BenchmarkDataError, ReleaseProvenanceError) as exc: + console.print(f"[red]Release provenance verification failed:[/red] {exc}") + raise click.exceptions.Exit(2) from exc + except ValueError as exc: + console.print(f"[red]Artifact context verification failed:[/red] {exc}") + raise click.exceptions.Exit(2) from exc + + if fmt == "json": + rendered = result.to_json() + elif fmt == "html": + rendered = result.to_html() + else: + rendered = result.summary() if output: - output.write_text(result.to_json()) + output.write_text(rendered, encoding="utf-8") console.print(f"Report written to {output}") else: - console.print(result.summary()) + if fmt == "text": + console.print(rendered) + else: + click.echo(rendered) + + if not result.verification_complete: + raise click.exceptions.Exit(2) @main.command() @@ -67,6 +285,12 @@ def validate(submission: Path) -> None: console.print("[green]Quarantine passed[/green]") sresult = validate_schema(submission) + if not sresult.performed: + console.print("ECMA-376 schema: [red]not performed[/red]") + for violation in sresult.violations: + console.print(f" - {violation}") + raise click.exceptions.Exit(2) + status = "[green]valid[/green]" if sresult.valid else "[yellow]invalid[/yellow]" console.print(f"ECMA-376 schema: {status}") if sresult.violations: @@ -74,17 +298,84 @@ def validate(submission: Path) -> None: console.print(f" - {v}") if len(sresult.violations) > 10: console.print(f" ... and {len(sresult.violations) - 10} more") + if not sresult.valid: + raise click.exceptions.Exit(1) @main.command() @click.argument("submission", type=click.Path(exists=True, path_type=Path)) @click.option("--outdir", type=click.Path(path_type=Path), default=Path("./exports")) -def export(submission: Path, outdir: Path) -> None: +@click.option( + "--pdf-output", + type=click.Path(dir_okay=False, path_type=Path), + default=None, + help="Optional retained canonical PDF used for release reproducibility evidence", +) +def export(submission: Path, outdir: Path, pdf_output: Path | None) -> None: """Export .pptx slides to PNG using LibreOffice headless.""" from acidslide.export import export_slides outdir.mkdir(parents=True, exist_ok=True) - slides = export_slides(submission, outdir) + slides = export_slides(submission, outdir, pdf_output=pdf_output) console.print(f"Exported {len(slides)} slides to {outdir}") for s in slides: - console.print(f" {s.name}") + console.print(f" {s.path.name}") + + +@main.command("scene-graph") +@click.argument("resolved_package", type=click.Path(exists=True, dir_okay=False, path_type=Path)) +@click.option( + "--output", + "-o", + type=click.Path(dir_okay=False, path_type=Path), + default=None, + help="RFC 8785 canonical deck scene-graph JSON; stdout when omitted", +) +@click.option( + "--slides-dir", + type=click.Path(file_okay=False, path_type=Path), + default=None, + help="Optional directory for independently schema-valid per-slide JSON", +) +@click.option( + "--profile", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + default=None, + help="Explicit scene-graph profile; defaults to the packaged v1 profile", +) +def scene_graph( + resolved_package: Path, + output: Path | None, + slides_dir: Path | None, + profile: Path | None, +) -> None: + """Extract deterministic structural evidence from an MCE-resolved PPTX.""" + from acidslide.scene_graph import ( + SceneGraphError, + canonical_scene_graph_bytes, + extract_normative_scene_graph, + per_slide_scene_graphs, + ) + + try: + graph = extract_normative_scene_graph(resolved_package, profile_path=profile) + encoded = canonical_scene_graph_bytes(graph) + if output is not None: + output.parent.mkdir(parents=True, exist_ok=True) + output.write_bytes(encoded) + if slides_dir is not None: + slides_dir.mkdir(parents=True, exist_ok=True) + for number, fixture in per_slide_scene_graphs(graph).items(): + (slides_dir / f"slide-{number:02d}.json").write_bytes( + canonical_scene_graph_bytes(fixture) + ) + except (OSError, SceneGraphError) as exc: + console.print(f"[red]Scene-graph extraction failed:[/red] {exc}") + raise click.exceptions.Exit(2) from exc + + if output is None: + click.echo(encoded.decode("utf-8")) + else: + console.print(f"Scene graph written to {output}") + if slides_dir is not None: + console.print(f"Per-slide scene graphs written to {slides_dir}") diff --git a/acidslide-v1/grader/acidslide/compare.py b/acidslide-v1/grader/acidslide/compare.py index 4ff4f38..110e21c 100644 --- a/acidslide-v1/grader/acidslide/compare.py +++ b/acidslide-v1/grader/acidslide/compare.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast import numpy as np from PIL import Image @@ -22,7 +22,7 @@ def compare_slides( diff_dir: Path | None = None, ) -> list[VisualComparisonResult]: """Compare exported submission slides against gold exports.""" - results = [] + results: list[VisualComparisonResult] = [] gold_slides = sorted(gold_dir.glob("slide-*.png")) for gold_path in gold_slides: @@ -52,21 +52,34 @@ def _compare_single( diff_dir: Path | None, ) -> VisualComparisonResult: """Compare two slide PNGs.""" - gold_img = np.array(Image.open(gold_path).convert("RGB")) - sub_img = np.array(Image.open(sub_path).convert("RGB")) + with Image.open(gold_path) as gold_source: + gold_img = np.array(gold_source.convert("RGB")) + with Image.open(sub_path) as submission_source: + sub_img = np.array(submission_source.convert("RGB")) - # Resize submission to match gold if needed + # Canonical exports must already have identical dimensions. Resizing would + # introduce a second, non-normative visual pipeline. if gold_img.shape != sub_img.shape: - sub_pil = Image.open(sub_path).convert("RGB") - sub_pil = sub_pil.resize((gold_img.shape[1], gold_img.shape[0]), Image.LANCZOS) - sub_img = np.array(sub_pil) + return VisualComparisonResult( + slide_number=slide_number, + ssim=0.0, + pixel_exact=False, + ) # Compute SSIM (RGB, per-channel then averaged) - ssim_score = ssim( - gold_img, - sub_img, - channel_axis=2, - data_range=255, + ssim_score = cast( + "float", + ssim( # type: ignore[no-untyped-call] + gold_img, + sub_img, + channel_axis=2, + data_range=255, + win_size=7, + gaussian_weights=False, + use_sample_covariance=True, + K1=0.01, + K2=0.03, + ), ) # Exact pixel match @@ -76,7 +89,7 @@ def _compare_single( diff_path = None if diff_dir and not pixel_exact: diff_dir.mkdir(parents=True, exist_ok=True) - diff_img = np.abs(gold_img.astype(np.int16) - sub_img.astype(np.int16)).astype(np.uint8) + diff_img = np.abs(gold_img.astype(np.int16) - sub_img.astype(np.int16)) # Amplify differences for visibility diff_img = np.clip(diff_img * 10, 0, 255).astype(np.uint8) diff_path = diff_dir / f"diff-slide-{slide_number:02d}.png" diff --git a/acidslide-v1/grader/acidslide/environment.py b/acidslide-v1/grader/acidslide/environment.py new file mode 100644 index 0000000..308524d --- /dev/null +++ b/acidslide-v1/grader/acidslide/environment.py @@ -0,0 +1,634 @@ +"""Fingerprint the actual grading environment used for a report.""" + +from __future__ import annotations + +import hashlib +import json +import locale +import os +import platform +import re +import shutil +import subprocess +import sys +from copy import deepcopy +from datetime import UTC, datetime +from importlib.metadata import PackageNotFoundError, version +from pathlib import Path, PurePosixPath +from typing import Any + +import rfc8785 +from jsonschema import Draft202012Validator + +from acidslide import __version__ +from acidslide.export import EXPORT_HEIGHT, EXPORT_WIDTH, find_libreoffice +from acidslide.profile_contract import environment_profile_hashes, load_render_profiles +from acidslide.resources import resolve_normative_schema_file +from acidslide.source_tree import build_grader_source_tree_manifest + +_PROCESS_ENVIRONMENT_KEYS = ( + "FAKETIME", + "FAKETIME_DONT_FAKE_MONOTONIC", + "FAKETIME_NO_CACHE", + "LD_PRELOAD", + "TZ", + "LANG", + "LC_ALL", +) +_PREFIXED_SHA256 = re.compile(r"^sha256:[0-9a-f]{64}$") +_DOCKER_DIGEST = re.compile( + r"^FROM\s+(?P\S+)@(?Psha256:[0-9a-f]{64})(?:\s+AS\s+(?P\S+))?\s*$", + re.MULTILINE | re.IGNORECASE, +) +_DEFAULT_DOCKERFILE = Path("/opt/acidslide/build/Dockerfile") +_DEFAULT_LOCKFILE = Path("/opt/acidslide/grader/uv.lock") +_DEFAULT_GRADER_ROOT = Path("/opt/acidslide/grader") + + +class EnvironmentAttestationError(ValueError): + """The running grader cannot reproduce the frozen environment payload.""" + + +def environment_details() -> dict[str, Any]: + """Collect the renderer, runtime, and dependency versions that affect grading.""" + details: dict[str, Any] = { + "grader_version": __version__, + "python": platform.python_version(), + "python_implementation": platform.python_implementation(), + "platform": platform.platform(), + "machine": platform.machine(), + "locale": _locale_name(), + "timezone": os.environ.get("TZ", "system-default"), + "export_width": EXPORT_WIDTH, + "export_height": EXPORT_HEIGHT, + "dependencies": { + package: _package_version(package) + for package in ("lxml", "numpy", "Pillow", "scikit-image") + }, + "libreoffice": _libreoffice_version(), + } + return details + + +def environment_hash(details: dict[str, Any] | None = None) -> str: + """Return a SHA-256 identifier for the effective grading environment.""" + if details is None: + details = environment_details() + payload = json.dumps(details, sort_keys=True, separators=(",", ":")).encode() + return hashlib.sha256(payload).hexdigest() + + +def environment_attestation_sha256(payload: dict[str, Any]) -> str: + """Hash one schema-valid environment payload using the normative JCS rule.""" + return f"sha256:{hashlib.sha256(rfc8785.dumps(payload)).hexdigest()}" + + +def runtime_freeze_input(payload: dict[str, Any]) -> dict[str, str]: + """Project one attestation into the separately validated manifest-builder input.""" + versions = payload.get("runtime_versions") + fonts = payload.get("font_environment") + binaries = payload.get("binary_inventory") + if ( + not isinstance(versions, dict) + or not isinstance(fonts, dict) + or not isinstance(binaries, list) + ): + raise EnvironmentAttestationError("Environment attestation cannot form a runtime freeze") + libfaketime = [ + record + for record in binaries + if isinstance(record, dict) and record.get("name") == "libfaketime" + ] + if len(libfaketime) != 1: + raise EnvironmentAttestationError("Environment attestation has no unique libfaketime file") + projection = { + "platform": payload.get("platform"), + "oci_image_digest": payload.get("oci_image_digest"), + **{ + name: versions.get(name) + for name in ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + ) + }, + "libfaketime_library_sha256": libfaketime[0].get("sha256"), + "fontconfig_config_sha256": fonts.get("fontconfig_config_sha256"), + "environment_attestation_sha256": environment_attestation_sha256(payload), + } + if not all(isinstance(value, str) and value for value in projection.values()): + raise EnvironmentAttestationError("Environment attestation runtime freeze is incomplete") + return projection # type: ignore[return-value] + + +def construct_environment_attestation_candidate( + *, + oci_image_digest: str, + attested_at: str, + canary_id: str, + canary_input_path: Path, + canary_report_path: Path, + schema_path: Path | None = None, + schema_dir: Path | None = None, + font_manifest_path: Path = Path("/opt/acidslide/benchmark/fonts/manifest.json"), + dockerfile_path: Path = _DEFAULT_DOCKERFILE, + grader_lockfile_path: Path = _DEFAULT_LOCKFILE, + grader_root: Path = _DEFAULT_GRADER_ROOT, + source_tree_profile_path: Path | None = None, +) -> tuple[dict[str, Any], dict[str, Any]]: + """Construct an honest, current-image candidate and its source-tree manifest. + + The result is not a frozen release identity. It becomes one only after the + immutable OCI digest, source tree, canary, evidence, manifest, and release + signatures are independently frozen. Every field emitted here is derived + from supplied bytes or reconstructed inside the isolated linux/amd64 image. + """ + _require_prefixed_sha256(oci_image_digest, "oci_image_digest") + _require_utc_timestamp(attested_at) + if not canary_id or not re.fullmatch(r"[a-z0-9][a-z0-9._-]{2,127}", canary_id): + raise EnvironmentAttestationError("canary_id is not a canonical v1 identifier") + platform_name = _platform_name() + if platform_name != "linux/amd64": + raise EnvironmentAttestationError( + f"Runtime platform is not the frozen linux/amd64 target: {platform_name}" + ) + process_environment = {name: os.environ.get(name, "") for name in _PROCESS_ENVIRONMENT_KEYS} + profiles = load_render_profiles(schema_dir) + source_manifest = _build_source_tree_manifest(grader_root, source_tree_profile_path, schema_dir) + source_sha256 = f"sha256:{hashlib.sha256(rfc8785.dumps(source_manifest)).hexdigest()}" + expected_font_environment = {"fontconfig_file": os.environ.get("FONTCONFIG_FILE")} + payload: dict[str, Any] = { + "schema_version": "1.0", + "attestation_id": "acidslide-environment-attestation-v1", + "canonicalization": "RFC8785-JCS", + "attestation_state": "verified", + "attested_at": attested_at, + "platform": platform_name, + "oci_image_digest": oci_image_digest, + "build_inputs": _build_inputs(dockerfile_path, grader_lockfile_path), + "runtime_versions": _runtime_versions(), + "binary_inventory": _current_binary_inventory(), + "font_environment": _font_environment(expected_font_environment, font_manifest_path), + "process_environment": process_environment, + "export_contract": profiles.export_contract(), + "profile_hashes": environment_profile_hashes(schema_dir), + "grader_source_tree_sha256": source_sha256, + "canary": { + "canary_id": canary_id, + "input_sha256": _sha256_path(canary_input_path), + "score_semantic_report_sha256": _sha256_path(canary_report_path), + }, + "verification": { + "architecture_verified": True, + "binary_hashes_verified": True, + "font_inventory_verified": True, + "clock_fixture_verified": _clock_fixture_is_verified(), + "network_disabled_verified": _network_is_disabled(), + }, + } + if not payload["verification"]["clock_fixture_verified"]: + raise EnvironmentAttestationError("Runtime clock fixture is not frozen to the v1 reference") + if not payload["verification"]["network_disabled_verified"]: + raise EnvironmentAttestationError("Runtime network namespace is not isolated") + resolved_schema = resolve_normative_schema_file( + "environment-attestation.schema.json", schema_path or schema_dir + ) + validator = _load_attestation_validator(resolved_schema) + _validate_attestation(validator, payload, "Candidate environment attestation") + return payload, source_manifest + + +def reconstruct_environment_attestation( + expected: dict[str, Any], + *, + oci_image_digest: str, + schema_path: Path | None = None, + schema_dir: Path | None = None, + font_manifest_path: Path = Path("/opt/acidslide/benchmark/fonts/manifest.json"), + dockerfile_path: Path = _DEFAULT_DOCKERFILE, + grader_lockfile_path: Path = _DEFAULT_LOCKFILE, + grader_root: Path = _DEFAULT_GRADER_ROOT, + source_tree_profile_path: Path | None = None, +) -> dict[str, Any]: + """Rebuild runtime-controlled attestation fields and require an exact match. + + Release-time identities that cannot be derived from inside an OCI filesystem + remain in the signed expected payload. Platform, runtime build strings, + executable bytes, Fontconfig state, font bytes, process inputs, and network + isolation are reconstructed from the live grading container. + """ + if not isinstance(expected, dict): + raise EnvironmentAttestationError("Expected environment attestation must be an object") + resolved_schema = resolve_normative_schema_file( + "environment-attestation.schema.json", schema_path or schema_dir + ) + validator = _load_attestation_validator(resolved_schema) + _validate_attestation(validator, expected, "Expected environment attestation") + if expected.get("oci_image_digest") != oci_image_digest: + raise EnvironmentAttestationError( + "Verified OCI image digest does not match the frozen environment attestation" + ) + + reconstructed = deepcopy(expected) + reconstructed["platform"] = _platform_name() + reconstructed["oci_image_digest"] = oci_image_digest + reconstructed["build_inputs"] = _build_inputs(dockerfile_path, grader_lockfile_path) + reconstructed["runtime_versions"] = _runtime_versions() + reconstructed["binary_inventory"] = _binary_inventory(expected.get("binary_inventory")) + reconstructed["font_environment"] = _font_environment( + expected.get("font_environment"), font_manifest_path + ) + reconstructed["process_environment"] = { + name: os.environ.get(name, "") for name in _PROCESS_ENVIRONMENT_KEYS + } + reconstructed["export_contract"] = load_render_profiles(schema_dir).export_contract() + reconstructed["profile_hashes"] = environment_profile_hashes(schema_dir) + source_manifest = _build_source_tree_manifest(grader_root, source_tree_profile_path, schema_dir) + reconstructed["grader_source_tree_sha256"] = ( + f"sha256:{hashlib.sha256(rfc8785.dumps(source_manifest)).hexdigest()}" + ) + if reconstructed["platform"] != "linux/amd64": + raise EnvironmentAttestationError( + f"Runtime platform is not the frozen linux/amd64 target: {reconstructed['platform']}" + ) + if not _network_is_disabled(): + raise EnvironmentAttestationError("Runtime network namespace is not isolated") + if not _clock_fixture_is_verified(): + raise EnvironmentAttestationError("Runtime clock fixture is not frozen to the v1 reference") + reconstructed["verification"] = { + "architecture_verified": True, + "binary_hashes_verified": True, + "font_inventory_verified": True, + "clock_fixture_verified": True, + "network_disabled_verified": True, + } + _validate_attestation(validator, reconstructed, "Reconstructed environment attestation") + if reconstructed != expected: + changed = sorted( + key + for key in set(expected) | set(reconstructed) + if expected.get(key) != reconstructed.get(key) + ) + raise EnvironmentAttestationError( + "Runtime environment attestation mismatch in: " + ", ".join(changed) + ) + return reconstructed + + +def _load_attestation_validator(path: Path) -> Draft202012Validator: + try: + schema = json.loads(path.read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + except (OSError, TypeError, ValueError, json.JSONDecodeError) as exc: + raise EnvironmentAttestationError( + f"Environment attestation schema is unreadable or invalid: {path}" + ) from exc + return Draft202012Validator(schema) + + +def _validate_attestation( + validator: Draft202012Validator, + payload: dict[str, Any], + label: str, +) -> None: + errors = sorted(validator.iter_errors(payload), key=lambda error: list(error.absolute_path)) + if errors: + location = "/".join(str(value) for value in errors[0].absolute_path) or "" + raise EnvironmentAttestationError(f"{label} is invalid at {location}: {errors[0].message}") + + +def _platform_name() -> str: + operating_system = platform.system().lower() + machine = platform.machine().lower() + architecture = "amd64" if machine in {"amd64", "x86_64"} else machine + return f"{operating_system}/{architecture}" + + +def _runtime_versions() -> dict[str, str]: + return { + "libreoffice": _command_version([str(find_libreoffice()), "--version"]), + "poppler": _command_version(["pdftoppm", "-v"]), + "python": platform.python_version(), + "pillow": _required_package_version("Pillow"), + "numpy": _required_package_version("numpy"), + "scikit_image": _required_package_version("scikit-image"), + "lxml": _required_package_version("lxml"), + "grader": __version__, + "libfaketime": _command_version(["dpkg-query", "-W", "-f=${Version}", "libfaketime"]), + "fontconfig": _command_version(["fc-list", "--version"]), + } + + +def _current_binary_inventory() -> list[dict[str, str]]: + paths = { + "fontconfig": _required_executable("fc-list"), + "libfaketime": _required_runtime_file( + Path("/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1") + ), + "libreoffice": find_libreoffice().resolve(), + "pdftoppm": _required_executable("pdftoppm"), + "python": Path(sys.executable).resolve(), + } + return [ + {"name": name, "path": str(path), "sha256": _sha256_path(path)} + for name, path in sorted(paths.items()) + ] + + +def _required_executable(name: str) -> Path: + value = shutil.which(name) + if not value: + raise EnvironmentAttestationError(f"Required runtime executable is missing: {name}") + path = Path(value).resolve() + if not path.is_file(): + raise EnvironmentAttestationError(f"Required runtime executable is unavailable: {path}") + return path + + +def _required_runtime_file(path: Path) -> Path: + resolved = path.resolve() + if not resolved.is_file(): + raise EnvironmentAttestationError(f"Required runtime file is unavailable: {path}") + return resolved + + +def _build_inputs(dockerfile_path: Path, grader_lockfile_path: Path) -> dict[str, str]: + try: + dockerfile = dockerfile_path.read_text(encoding="utf-8") + except OSError as exc: + raise EnvironmentAttestationError( + f"Attested Dockerfile is unreadable: {dockerfile_path}" + ) from exc + matches = list(_DOCKER_DIGEST.finditer(dockerfile)) + base_digests = [ + match.group("digest") + for match in matches + if match.group("image").lower().startswith("ubuntu:") + ] + uv_digests = [ + match.group("digest") + for match in matches + if match.group("stage") and match.group("stage").lower() == "uv" + ] + if len(base_digests) != 1 or len(uv_digests) != 1: + raise EnvironmentAttestationError( + "Dockerfile must contain exactly one digest-pinned Ubuntu base and uv stage" + ) + return { + "dockerfile_sha256": _sha256_path(dockerfile_path), + "grader_lockfile_sha256": _sha256_path(grader_lockfile_path), + "base_image_digest": base_digests[0], + "uv_image_digest": uv_digests[0], + } + + +def _build_source_tree_manifest( + grader_root: Path, + source_tree_profile_path: Path | None, + schema_dir: Path | None, +) -> dict[str, Any]: + profile = resolve_normative_schema_file( + "grader-source-tree-profile-v1.json", source_tree_profile_path or schema_dir + ) + try: + return build_grader_source_tree_manifest(grader_root, profile) + except (OSError, RuntimeError, ValueError) as exc: + raise EnvironmentAttestationError( + f"Grader source tree cannot be reconstructed: {grader_root}" + ) from exc + + +def _clock_fixture_is_verified() -> bool: + if os.environ.get("LD_PRELOAD") != "/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1": + return False + try: + completed = subprocess.run( + ["date", "-u", "+%Y-%m-%dT%H:%M:%SZ"], + capture_output=True, + check=True, + text=True, + timeout=10, + ) + except (OSError, subprocess.SubprocessError): + return False + return completed.stdout.strip() == "2025-01-01T00:00:00Z" + + +def _require_prefixed_sha256(value: str, name: str) -> None: + if not isinstance(value, str) or not _PREFIXED_SHA256.fullmatch(value): + raise EnvironmentAttestationError(f"{name} is not a canonical prefixed SHA-256") + + +def _require_utc_timestamp(value: str) -> None: + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except (TypeError, ValueError) as exc: + raise EnvironmentAttestationError("attested_at is not an RFC 3339 timestamp") from exc + if not value.endswith("Z") or parsed.tzinfo != UTC: + raise EnvironmentAttestationError("attested_at must be serialized in UTC with Z") + + +def _required_package_version(package: str) -> str: + value = _package_version(package) + if value == "not-installed": + raise EnvironmentAttestationError(f"Required scoring library is not installed: {package}") + return value + + +def _command_version(command: list[str]) -> str: + try: + completed = subprocess.run( + command, + capture_output=True, + check=True, + text=True, + timeout=10, + ) + except (OSError, subprocess.SubprocessError) as exc: + raise EnvironmentAttestationError( + f"Required runtime version command failed: {command[0]}" + ) from exc + output = "\n".join( + value.strip() for value in (completed.stdout, completed.stderr) if value.strip() + ) + if not output: + raise EnvironmentAttestationError( + f"Required runtime version command returned no build ID: {command[0]}" + ) + return output + + +def _binary_inventory(value: object) -> list[dict[str, str]]: + if not isinstance(value, list) or not value: + raise EnvironmentAttestationError("Frozen binary inventory is missing") + inventory: list[dict[str, str]] = [] + identities: set[str] = set() + for record in value: + if not isinstance(record, dict): + raise EnvironmentAttestationError("Frozen binary inventory is malformed") + name = record.get("name") + raw_path = record.get("path") + if not isinstance(name, str) or not isinstance(raw_path, str): + raise EnvironmentAttestationError("Frozen binary inventory is malformed") + path = Path(raw_path) + if not path.is_absolute() or not path.is_file(): + raise EnvironmentAttestationError(f"Attested executable is unavailable: {raw_path}") + if name in identities: + raise EnvironmentAttestationError(f"Duplicate attested executable name: {name}") + identities.add(name) + inventory.append({"name": name, "path": raw_path, "sha256": _sha256_path(path)}) + return sorted(inventory, key=lambda record: (record["name"], record["path"])) + + +def _font_environment(value: object, manifest_path: Path) -> dict[str, Any]: + if not isinstance(value, dict): + raise EnvironmentAttestationError("Frozen font environment is missing") + configured_path = os.environ.get("FONTCONFIG_FILE") + if not configured_path: + raise EnvironmentAttestationError("FONTCONFIG_FILE is not set") + fontconfig_file = Path(configured_path) + if not fontconfig_file.is_absolute() or not fontconfig_file.is_file(): + raise EnvironmentAttestationError( + f"Fontconfig configuration is unavailable: {configured_path}" + ) + expected_fontconfig = value.get("fontconfig_file") + if expected_fontconfig != configured_path: + raise EnvironmentAttestationError( + "FONTCONFIG_FILE does not match the frozen environment attestation" + ) + try: + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + except (OSError, TypeError, ValueError, json.JSONDecodeError) as exc: + raise EnvironmentAttestationError(f"Font manifest is unreadable: {manifest_path}") from exc + files = manifest.get("files") if isinstance(manifest, dict) else None + if not isinstance(files, list) or not files: + raise EnvironmentAttestationError("Font manifest has no file inventory") + expected_fonts: dict[str, str] = {} + for record in files: + if not isinstance(record, dict): + raise EnvironmentAttestationError("Font manifest file inventory is malformed") + local_path = record.get("local_path") + sha256 = record.get("sha256") + if not isinstance(local_path, str) or not isinstance(sha256, str): + raise EnvironmentAttestationError("Font manifest file inventory is malformed") + relative = PurePosixPath(local_path) + if relative.is_absolute() or any(part in {"", ".", ".."} for part in relative.parts): + raise EnvironmentAttestationError(f"Unsafe font manifest path: {local_path!r}") + absolute = str((manifest_path.parent / Path(*relative.parts)).resolve()) + if absolute in expected_fonts: + raise EnvironmentAttestationError(f"Duplicate font manifest path: {local_path}") + expected_fonts[absolute] = sha256.removeprefix("sha256:") + discovered = _discover_font_paths() + if set(discovered) != set(expected_fonts): + missing = sorted(set(expected_fonts) - set(discovered)) + extra = sorted(set(discovered) - set(expected_fonts)) + raise EnvironmentAttestationError( + f"Fontconfig inventory mismatch: missing={missing} extra={extra}" + ) + records: list[dict[str, str]] = [] + for raw_path in discovered: + path = Path(raw_path) + actual = _sha256_path(path) + if actual.removeprefix("sha256:") != expected_fonts[raw_path]: + raise EnvironmentAttestationError(f"Font file hash mismatch: {raw_path}") + records.append({"path": raw_path, "sha256": actual}) + return { + "fontconfig_file": configured_path, + "fontconfig_config_sha256": _sha256_path(fontconfig_file), + "font_manifest_sha256": _sha256_path(manifest_path), + "discovered_fonts": records, + "exact_manifest_match": True, + } + + +def _discover_font_paths() -> list[str]: + try: + completed = subprocess.run( + ["fc-list", "-f", "%{file}\\n"], + capture_output=True, + check=True, + text=True, + timeout=30, + ) + except (OSError, subprocess.SubprocessError) as exc: + raise EnvironmentAttestationError("Fontconfig inventory command failed") from exc + paths = sorted(set(completed.stdout.splitlines())) + if not paths or any(not Path(path).is_absolute() for path in paths): + raise EnvironmentAttestationError("Fontconfig returned a malformed or empty inventory") + return paths + + +def _network_is_disabled() -> bool: + interface_root = Path("/sys/class/net") + try: + interfaces = {path.name for path in interface_root.iterdir()} + states = { + name: (interface_root / name / "operstate").read_text(encoding="utf-8").strip() + for name in interfaces + if (interface_root / name / "operstate").is_file() + } + ipv4_routes = (Path("/proc/net/route")).read_text(encoding="utf-8").splitlines()[1:] + ipv6_routes = (Path("/proc/net/ipv6_route")).read_text(encoding="utf-8").splitlines() + except OSError as exc: + raise EnvironmentAttestationError("Cannot inspect the runtime network namespace") from exc + non_loopback_up = any(name != "lo" and state != "down" for name, state in states.items()) + non_loopback_ipv4_route = any( + fields and fields[0] != "lo" for fields in (line.split() for line in ipv4_routes) + ) + non_loopback_ipv6_route = any( + fields and fields[-1] != "lo" for fields in (line.split() for line in ipv6_routes) + ) + return ( + "lo" in interfaces + and not non_loopback_up + and not non_loopback_ipv4_route + and not non_loopback_ipv6_route + ) + + +def _sha256_path(path: Path) -> str: + try: + digest = hashlib.sha256(path.read_bytes()).hexdigest() + except OSError as exc: + raise EnvironmentAttestationError(f"Attested runtime file is unreadable: {path}") from exc + return f"sha256:{digest}" + + +def _package_version(package: str) -> str: + try: + return version(package) + except PackageNotFoundError: + return "not-installed" + + +def _libreoffice_version() -> str: + try: + executable = find_libreoffice() + except RuntimeError: + return "not-installed" + + try: + completed = subprocess.run( + [str(executable), "--version"], + capture_output=True, + check=True, + text=True, + timeout=10, + ) + except (OSError, subprocess.SubprocessError): + return "unavailable" + return completed.stdout.strip() or completed.stderr.strip() or "unknown" + + +def _locale_name() -> str: + try: + return locale.setlocale(locale.LC_ALL, None) + except locale.Error: + return sys.getdefaultencoding() diff --git a/acidslide-v1/grader/acidslide/evaluate.py b/acidslide-v1/grader/acidslide/evaluate.py index a6e29b5..662344f 100644 --- a/acidslide-v1/grader/acidslide/evaluate.py +++ b/acidslide-v1/grader/acidslide/evaluate.py @@ -4,11 +4,18 @@ from typing import TYPE_CHECKING +from acidslide.affected_slides import resolve_named_selector from acidslide.checklist import SEVERITY_WEIGHTS, ChecklistItem -from acidslide.inspect_ooxml import DeckGraph, SceneObject, SlideGraph -from acidslide.models import ChecklistItemResult, Severity, SlideResult, SourceOfTruth +from acidslide.models import ( + AntiCheatFlag, + ChecklistItemResult, + Severity, + SlideResult, + SourceOfTruth, +) if TYPE_CHECKING: + from acidslide.inspect_ooxml import DeckGraph, SceneObject, SlideGraph from acidslide.models import VisualComparisonResult # Allowed fonts per §3 / §4.3 @@ -41,13 +48,13 @@ def evaluate_checklist( items: list[ChecklistItem], visual_results: list[VisualComparisonResult] | None = None, tier_slides: list[int] | None = None, -) -> tuple[list[SlideResult], list[ChecklistItemResult], list[str]]: +) -> tuple[list[SlideResult], list[ChecklistItemResult], list[AntiCheatFlag]]: """Evaluate all checklist items against the deck graph. Returns: - slide_results: per-slide results with item pass/fail - deck_item_results: deck-scoped item results - - anti_cheat_flags: triggered anti-cheat rule names + - anti_cheat_flags: triggered anti-cheat rules and exact propagation """ visual_by_slide: dict[int, VisualComparisonResult] = {} if visual_results: @@ -55,8 +62,8 @@ def evaluate_checklist( visual_by_slide[vr.slide_number] = vr slide_graph_by_num: dict[int, SlideGraph] = {} - for sg in deck_graph.slides: - slide_graph_by_num[sg.slide_number] = sg + for slide_graph in deck_graph.slides: + slide_graph_by_num[slide_graph.slide_number] = slide_graph # Separate slide-level and deck-level items slide_items: dict[int, list[ChecklistItem]] = {} @@ -67,19 +74,26 @@ def evaluate_checklist( elif item.slide is not None: slide_items.setdefault(item.slide, []).append(item) + effective_tier_slides = sorted( + set(tier_slides) if tier_slides is not None else set(slide_graph_by_num) + ) + anti_cheat_flags: list[AntiCheatFlag] = [] + zeroed_slides: set[int] = set() + # Evaluate deck-level items deck_item_results: list[ChecklistItemResult] = [] for item in deck_items: - result = _evaluate_deck_item(item, deck_graph) + result = _evaluate_deck_item(item, deck_graph, list(visual_by_slide.values())) + _decorate_result(result, item, effective_tier_slides) deck_item_results.append(result) + if not result.passed and item.failure_mode.automatic_fail_if: + affected = _failure_affected_slides(item, None, deck_graph) + tier_affected = sorted(set(affected) & set(effective_tier_slides)) + zeroed_slides.update(tier_affected) + anti_cheat_flags.extend(_build_anti_cheat_flags(item, result, affected, tier_affected)) # Evaluate slide-level items - anti_cheat_flags: list[str] = [] - zeroed_slides: set[int] = set() - - all_slide_nums = sorted( - set(slide_graph_by_num.keys()) | set(slide_items.keys()) - ) + all_slide_nums = sorted(set(slide_graph_by_num.keys()) | set(slide_items.keys())) if tier_slides is not None: all_slide_nums = [n for n in all_slide_nums if n in tier_slides] @@ -101,13 +115,17 @@ def evaluate_checklist( source_of_truth=SourceOfTruth(item.source_of_truth), details=f"Slide {slide_num} not found in submission", ) + _decorate_result(result, item, [slide_num]) # Check for auto-fail propagation if not result.passed and item.failure_mode.automatic_fail_if: - for flag in item.failure_mode.automatic_fail_if: - anti_cheat_flags.append(f"slide-{slide_num:02d}.{flag}") + affected = _failure_affected_slides(item, slide_num, deck_graph) + tier_affected = sorted(set(affected) & set(effective_tier_slides)) + anti_cheat_flags.extend( + _build_anti_cheat_flags(item, result, affected, tier_affected) + ) if item.failure_mode.propagation == "zero_slide": - zeroed_slides.add(slide_num) + zeroed_slides.update(tier_affected) item_results.append(result) @@ -126,13 +144,74 @@ def evaluate_checklist( for item_result in sr.items: if item_result.passed: item_result.passed = False - item_result.details = ( - f"Zeroed by anti-cheat rule on slide {sr.slide_number}" - ) + item_result.details = f"Zeroed by anti-cheat rule on slide {sr.slide_number}" + item_result.outcome_code = "zeroed_by_anti_cheat" return slide_results, deck_item_results, anti_cheat_flags +def _decorate_result( + result: ChecklistItemResult, + item: ChecklistItem, + tier_affected_slides: list[int], +) -> None: + result.assertion_id = item.assertion_id or _derived_assertion_id(item.id) + result.weight = item.weight + result.outcome_code = "passed" if result.passed else "failed" + result.tier_affected_slides = sorted(set(tier_affected_slides)) + + +def _derived_assertion_id(item_id: str) -> str: + prefix, separator, suffix = item_id.partition(".") + if not separator: + return f"deck.assert-{item_id}" + return f"{prefix}.assert-{suffix}" + + +def _failure_affected_slides( + item: ChecklistItem, + current_slide: int | None, + deck: DeckGraph, +) -> list[int]: + mode = item.failure_mode.affected_slides.get("mode") + if mode == "named_selector": + selector_id = item.failure_mode.affected_slides.get("selector_id") + selector_sha256 = item.failure_mode.affected_slides.get("selector_sha256") + if not isinstance(selector_id, str) or not isinstance(selector_sha256, str): + raise ValueError(f"Incomplete named affected-slide selector for {item.id}") + return resolve_named_selector(selector_id, selector_sha256, deck, BUNDLED_FONTS) + + configured = item.failure_mode.affected_slides.get("slides", []) + if ( + configured + and isinstance(configured, list) + and all(isinstance(value, int) and not isinstance(value, bool) for value in configured) + ): + return sorted(set(configured)) + return [current_slide] if current_slide is not None else [] + + +def _build_anti_cheat_flags( + item: ChecklistItem, + result: ChecklistItemResult, + affected_slides: list[int], + tier_affected_slides: list[int], +) -> list[AntiCheatFlag]: + disposition = item.failure_mode.propagation + if disposition not in {"zero_slide", "zero_affected_slides"}: + disposition = "warning" + return [ + AntiCheatFlag( + rule_id=rule_id, + disposition=disposition, + affected_slides=tuple(affected_slides), + tier_affected_slides=tuple(tier_affected_slides), + details=result.details, + ) + for rule_id in item.failure_mode.automatic_fail_if + ] + + def compute_fidelity_score( slide_results: list[SlideResult], deck_item_results: list[ChecklistItemResult], @@ -175,29 +254,25 @@ def compute_tier_scores( slide_results: list[SlideResult], deck_item_results: list[ChecklistItemResult], tier: int, -) -> dict[str, dict]: - """Compute per-tier fidelity scores.""" +) -> dict[str, dict[str, int | float] | None]: + """Compute only the targeted tier score; non-targeted tiers are null.""" tier_map: dict[int, list[int]] = { 1: list(range(1, 6)), 2: list(range(1, 13)), 3: list(range(1, 21)), } - scores: dict[str, dict] = {} + scores: dict[str, dict[str, int | float] | None] = {} for t in range(1, 4): - if t > tier: - scores[f"level_{t}"] = None # type: ignore[assignment] + if t != tier: + scores[f"level_{t}"] = None continue tier_slide_nums = set(tier_map[t]) - tier_slide_results = [ - sr for sr in slide_results if sr.slide_number in tier_slide_nums - ] + tier_slide_results = [sr for sr in slide_results if sr.slide_number in tier_slide_nums] # Deck items apply to all tiers - fidelity, passed, total = compute_fidelity_score( - tier_slide_results, deck_item_results - ) + fidelity, passed, total = compute_fidelity_score(tier_slide_results, deck_item_results) scores[f"level_{t}"] = { "fidelity_score": round(fidelity, 4), "passed": passed, @@ -244,6 +319,7 @@ def _evaluate_slide_item( def _evaluate_deck_item( item: ChecklistItem, deck: DeckGraph, + visual_results: list[VisualComparisonResult], ) -> ChecklistItemResult: """Evaluate a single deck-level checklist item.""" method = item.verification.method @@ -255,6 +331,8 @@ def _evaluate_deck_item( return _verify_deck_anti_cheat(item, deck) if method == "hash_match": return _verify_deck_hash_match(item, deck) + if method == "visual_ssim": + return _verify_deck_visual_ssim(item, visual_results) return ChecklistItemResult( id=item.id, passed=False, @@ -267,9 +345,7 @@ def _evaluate_deck_item( # --- Verification implementations --- -def _verify_object_compare( - item: ChecklistItem, slide: SlideGraph -) -> ChecklistItemResult: +def _verify_object_compare(item: ChecklistItem, slide: SlideGraph) -> ChecklistItemResult: """Verify object presence/count on a slide by type selector.""" selector = item.verification.selector expectation = item.verification.expectation @@ -304,9 +380,7 @@ def _verify_object_compare( ) -def _verify_text_match( - item: ChecklistItem, slide: SlideGraph -) -> ChecklistItemResult: +def _verify_text_match(item: ChecklistItem, slide: SlideGraph) -> ChecklistItemResult: """Verify text content exists on a slide.""" expectation = item.verification.expectation expected_text = expectation.get("contains", "") @@ -323,7 +397,7 @@ def _verify_text_match( details = f"Expected text containing '{expected_text}' not found" elif exact_text and exact_text != all_text.strip(): passed = False - details = f"Text does not exactly match expected" + details = "Text does not exactly match expected" elif not_contains and not_contains in all_text: passed = False details = f"Found prohibited text '{not_contains}'" @@ -349,7 +423,7 @@ def _verify_hash_match( # Collect picture objects on this slide all_objects = _collect_objects_recursive(slide.objects) - pictures = [o for o in all_objects if o.obj_type == "picture"] + pictures = [o for o in all_objects if o.is_picture] if not pictures: return ChecklistItemResult( @@ -362,9 +436,7 @@ def _verify_hash_match( if expected_hash: # Check if any embedded media matches the expected hash - found = any( - h == expected_hash for h in deck.media_hashes.values() - ) + found = any(h == expected_hash for h in deck.media_hashes.values()) return ChecklistItemResult( id=item.id, passed=found, @@ -382,9 +454,7 @@ def _verify_hash_match( ) -def _verify_field_check( - item: ChecklistItem, slide: SlideGraph -) -> ChecklistItemResult: +def _verify_field_check(item: ChecklistItem, slide: SlideGraph) -> ChecklistItemResult: """Verify native field presence (slidenum, datetime, etc.).""" expectation = item.verification.expectation expected_field = expectation.get("field_type", "") @@ -426,9 +496,7 @@ def _verify_layout_check( placeholders = [o for o in all_objects if o.placeholder_type] if expected_type: - placeholders = [ - o for o in placeholders if o.placeholder_type == expected_type - ] + placeholders = [o for o in placeholders if o.placeholder_type == expected_type] passed = len(placeholders) >= min_count return ChecklistItemResult( @@ -436,7 +504,10 @@ def _verify_layout_check( passed=passed, severity=Severity(item.severity), source_of_truth=SourceOfTruth(item.source_of_truth), - details=f"Found {len(placeholders)} '{expected_type or 'any'}' placeholder(s), need {min_count}", + details=( + f"Found {len(placeholders)} '{expected_type or 'any'}' placeholder(s), " + f"need {min_count}" + ), ) if selector == "master_ref": @@ -516,9 +587,7 @@ def _verify_visual_ssim( # --- Deck-level verification --- -def _verify_deck_object_compare( - item: ChecklistItem, deck: DeckGraph -) -> ChecklistItemResult: +def _verify_deck_object_compare(item: ChecklistItem, deck: DeckGraph) -> ChecklistItemResult: """Deck-level object count/presence check.""" expectation = item.verification.expectation selector = item.verification.selector @@ -543,9 +612,7 @@ def _verify_deck_object_compare( ) -def _verify_deck_layout_check( - item: ChecklistItem, deck: DeckGraph -) -> ChecklistItemResult: +def _verify_deck_layout_check(item: ChecklistItem, deck: DeckGraph) -> ChecklistItemResult: """Verify deck-level layout/master usage.""" expectation = item.verification.expectation selector = item.verification.selector @@ -581,9 +648,7 @@ def _verify_deck_layout_check( ) -def _verify_deck_anti_cheat( - item: ChecklistItem, deck: DeckGraph -) -> ChecklistItemResult: +def _verify_deck_anti_cheat(item: ChecklistItem, deck: DeckGraph) -> ChecklistItemResult: """Deck-level anti-cheat checks.""" selector = item.verification.selector @@ -598,9 +663,7 @@ def _verify_deck_anti_cheat( if run.font_family and not run.font_family.startswith("+"): rendered_fonts.add(run.font_family) - bad_rendered = { - f for f in rendered_fonts if f.lower() not in BUNDLED_FONTS - } + bad_rendered = {f for f in rendered_fonts if f.lower() not in BUNDLED_FONTS} # Also note theme fonts for informational purposes theme_only = deck.all_fonts - rendered_fonts @@ -626,15 +689,17 @@ def _verify_deck_anti_cheat( ) if selector == "no_notes": - # Check via deck metadata — extracted from content types during inspection - # For now, notes detection would require checking the ZIP directly - # This is handled separately in quarantine expansion + affected = sorted(deck.notes_slides | deck.comment_slides) return ChecklistItemResult( id=item.id, - passed=True, # placeholder — will be enhanced + passed=not affected, severity=Severity(item.severity), source_of_truth=SourceOfTruth(item.source_of_truth), - details="Notes detection via ZIP inspection (see quarantine)", + details=( + f"Notes or comments found on slides: {affected}" + if affected + else "No slide notes or comments detected" + ), ) return ChecklistItemResult( @@ -646,9 +711,7 @@ def _verify_deck_anti_cheat( ) -def _verify_deck_hash_match( - item: ChecklistItem, deck: DeckGraph -) -> ChecklistItemResult: +def _verify_deck_hash_match(item: ChecklistItem, deck: DeckGraph) -> ChecklistItemResult: """Verify deck-level asset hash requirements.""" expectation = item.verification.expectation expected_hashes = expectation.get("asset_hashes", {}) @@ -671,7 +734,39 @@ def _verify_deck_hash_match( passed=passed, severity=Severity(item.severity), source_of_truth=SourceOfTruth(item.source_of_truth), - details=f"Missing asset hashes: {list(missing.keys())}" if missing else "All asset hashes matched", + details=f"Missing asset hashes: {list(missing.keys())}" + if missing + else "All asset hashes matched", + ) + + +def _verify_deck_visual_ssim( + item: ChecklistItem, + visual_results: list[VisualComparisonResult], +) -> ChecklistItemResult: + """Require every targeted slide render to meet the deck-level SSIM floor.""" + threshold = float(item.verification.expectation.get("min_ssim", 0.9999)) + if not visual_results: + return ChecklistItemResult( + id=item.id, + passed=False, + severity=Severity(item.severity), + source_of_truth=SourceOfTruth(item.source_of_truth), + details="No visual comparison results available", + ) + + failures = [result for result in visual_results if result.ssim < threshold] + minimum = min(result.ssim for result in visual_results) + average = sum(result.ssim for result in visual_results) / len(visual_results) + return ChecklistItemResult( + id=item.id, + passed=not failures, + severity=Severity(item.severity), + source_of_truth=SourceOfTruth(item.source_of_truth), + details=( + f"{len(visual_results) - len(failures)}/{len(visual_results)} slides meet " + f"SSIM {threshold:.4f}; minimum={minimum:.4f}, mean={average:.4f}" + ), ) @@ -695,7 +790,7 @@ def _matches_selector(obj: SceneObject, selector: str) -> bool: if selector == "chart": return obj.is_chart if selector == "picture": - return obj.obj_type == "picture" + return obj.is_picture if selector == "group": return obj.obj_type == "group" if selector == "connector": @@ -703,7 +798,15 @@ def _matches_selector(obj: SceneObject, selector: str) -> bool: if selector == "placeholder": return bool(obj.placeholder_type) if selector == "shape": - return obj.obj_type == "shape" + return obj.obj_type in { + "shape", + "picture", + "table", + "chart", + "group", + "connector", + "graphicFrame", + } if selector == "field": return bool(obj.field_type) return obj.obj_type == selector @@ -718,16 +821,17 @@ def _collect_all_text(slide: SlideGraph) -> str: return " ".join(texts) -def _check_font_policy( - item: ChecklistItem, objects: list[SceneObject] -) -> ChecklistItemResult: +def _check_font_policy(item: ChecklistItem, objects: list[SceneObject]) -> ChecklistItemResult: """Check that all fonts on a slide are in the bundled set.""" bad_fonts: set[str] = set() for obj in objects: for run in obj.text_runs: - if run.font_family and run.font_family.lower() not in BUNDLED_FONTS: - if not run.font_family.startswith("+"): - bad_fonts.add(run.font_family) + if ( + run.font_family + and run.font_family.lower() not in BUNDLED_FONTS + and not run.font_family.startswith("+") + ): + bad_fonts.add(run.font_family) passed = len(bad_fonts) == 0 return ChecklistItemResult( @@ -735,7 +839,9 @@ def _check_font_policy( passed=passed, severity=Severity(item.severity), source_of_truth=SourceOfTruth(item.source_of_truth), - details=f"Non-bundled fonts: {sorted(bad_fonts)}" if bad_fonts else "All fonts in bundled set", + details=f"Non-bundled fonts: {sorted(bad_fonts)}" + if bad_fonts + else "All fonts in bundled set", ) @@ -748,7 +854,7 @@ def _check_no_full_slide_raster( threshold = 0.4 for obj in objects: - if obj.obj_type == "picture": + if obj.is_picture: _, _, cx, cy = obj.bbox if cx > 0 and cy > 0: obj_area = cx * cy @@ -759,7 +865,10 @@ def _check_no_full_slide_raster( passed=False, severity=Severity(item.severity), source_of_truth=SourceOfTruth(item.source_of_truth), - details=f"Image '{obj.name}' covers {ratio:.1%} of slide (>{threshold:.0%} threshold)", + details=( + f"Image '{obj.name}' covers {ratio:.1%} of slide " + f"(>{threshold:.0%} threshold)" + ), ) return ChecklistItemResult( diff --git a/acidslide-v1/grader/acidslide/export.py b/acidslide-v1/grader/acidslide/export.py index 8b731b2..3f4b93d 100644 --- a/acidslide-v1/grader/acidslide/export.py +++ b/acidslide-v1/grader/acidslide/export.py @@ -2,24 +2,47 @@ from __future__ import annotations +import os +import re import shutil import subprocess import tempfile +from decimal import Decimal from pathlib import Path +from PIL import Image +from pypdf import PdfReader + from acidslide.models import SlideExport +from acidslide.resources import resolve_benchmark_dir EXPORT_WIDTH = 1920 EXPORT_HEIGHT = 1080 EXPORT_TIMEOUT = 120 # seconds +# LibreOffice 7.3.7.2 rounds the exact 12192000-EMU width through its +# 1/100-mm internal unit. The raw PDF box is normative; rounded pdfinfo text +# is not evidence for this gate. +PDF_WIDTH_POINTS = Decimal("960.009448818898") +PDF_HEIGHT_POINTS = Decimal("540") +_PDF_NUMBER = rb"[+-]?(?:\d+(?:\.\d*)?|\.\d+)" +_ALLOWED_LIBREOFFICE_STDERR_LINES = { + "Warning: failed to launch javaldx - java may not function correctly", +} -def export_slides(pptx_path: Path, output_dir: Path) -> list[SlideExport]: +def export_slides( + pptx_path: Path, + output_dir: Path, + *, + expected_page_count: int | None = None, + pdf_output: Path | None = None, +) -> list[SlideExport]: """Export all slides from a .pptx to PNG using LibreOffice headless. Returns a list of SlideExport objects with paths to the exported PNGs. """ - libreoffice = _find_libreoffice() + libreoffice = find_libreoffice() + output_dir.mkdir(parents=True, exist_ok=True) with tempfile.TemporaryDirectory() as tmpdir: tmp = Path(tmpdir) @@ -28,60 +51,46 @@ def export_slides(pptx_path: Path, output_dir: Path) -> list[SlideExport]: tmp_pptx = tmp / pptx_path.name shutil.copy2(pptx_path, tmp_pptx) - # Try direct PNG export first - subprocess.run( - [ - str(libreoffice), - "--headless", - "--convert-to", - "png", - "--outdir", - str(tmp), - str(tmp_pptx), - ], - capture_output=True, - text=True, - timeout=EXPORT_TIMEOUT, + # V1 has one normative export path. Direct PNG export and alternate + # rasterizers are deliberately not fallbacks because they produce + # different pixels. + return _export_via_pdf( + tmp_pptx, + output_dir, + libreoffice, + expected_page_count=expected_page_count, + pdf_output=pdf_output, ) - # LibreOffice single-file PNG export only gives slide 1. - # Use PDF intermediate for all slides. - png_files = sorted(tmp.glob("*.png")) - - if len(png_files) <= 1: - # Fallback: PPTX → PDF → PNG per page - return _export_via_pdf(tmp_pptx, output_dir, libreoffice) - # Move PNGs to output directory with sequential naming - exports = [] - for i, png in enumerate(png_files, 1): - dest = output_dir / f"slide-{i:02d}.png" - shutil.move(str(png), str(dest)) - exports.append(SlideExport(slide_number=i, path=dest)) - - return exports - - -def _export_via_pdf(pptx_path: Path, output_dir: Path, libreoffice: Path) -> list[SlideExport]: +def _export_via_pdf( + pptx_path: Path, + output_dir: Path, + libreoffice: Path, + *, + expected_page_count: int | None = None, + pdf_output: Path | None = None, +) -> list[SlideExport]: """Export via PDF intermediate: PPTX → PDF → per-page PNG.""" with tempfile.TemporaryDirectory() as tmpdir: tmp = Path(tmpdir) + profile = tmp / "lo-profile" + libreoffice_environment = _libreoffice_environment(tmp) # Step 1: PPTX → PDF - subprocess.run( + _run_conversion( [ str(libreoffice), "--headless", + f"-env:UserInstallation={profile.as_uri()}", "--convert-to", "pdf", "--outdir", str(tmp), str(pptx_path), ], - capture_output=True, - text=True, - timeout=EXPORT_TIMEOUT, check=True, + env=libreoffice_environment, ) pdf_files = list(tmp.glob("*.pdf")) @@ -92,58 +101,61 @@ def _export_via_pdf(pptx_path: Path, output_dir: Path, libreoffice: Path) -> lis pdf_path = pdf_files[0] # Step 2: PDF → per-page PNG using Pillow (if available) or pdftoppm - return _pdf_to_pngs(pdf_path, output_dir) + exports = _pdf_to_pngs( + pdf_path, + output_dir, + expected_page_count=expected_page_count, + ) + if pdf_output is not None: + pdf_output.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(pdf_path, pdf_output) + return exports -def _pdf_to_pngs(pdf_path: Path, output_dir: Path) -> list[SlideExport]: +def _pdf_to_pngs( + pdf_path: Path, + output_dir: Path, + *, + expected_page_count: int | None = None, +) -> list[SlideExport]: """Convert PDF pages to PNGs at 1920x1080.""" + if expected_page_count is not None: + _validate_pdf_geometry(pdf_path, expected_page_count) # Try pdftoppm first (poppler-utils) pdftoppm = shutil.which("pdftoppm") if pdftoppm: - subprocess.run( + prefix = output_dir / "acidslide-render" + _run_conversion( [ pdftoppm, "-png", - "-rx", - "150", # DPI for ~1920px width at 16:9 - "-ry", - "150", + "-scale-to-x", + str(EXPORT_WIDTH), + "-scale-to-y", + str(EXPORT_HEIGHT), str(pdf_path), - str(output_dir / "slide"), + str(prefix), ], - capture_output=True, - text=True, - timeout=EXPORT_TIMEOUT, check=True, ) - exports = [] - for i, png in enumerate(sorted(output_dir.glob("slide-*.png")), 1): - dest = output_dir / f"slide-{i:02d}.png" - if png != dest: - png.rename(dest) - exports.append(SlideExport(slide_number=i, path=dest)) - return exports - - # Fallback: use pdf2image if installed - try: - from pdf2image import convert_from_path - - images = convert_from_path(str(pdf_path), size=(EXPORT_WIDTH, EXPORT_HEIGHT)) - exports = [] - for i, img in enumerate(images, 1): - dest = output_dir / f"slide-{i:02d}.png" - img.save(str(dest), "PNG") - exports.append(SlideExport(slide_number=i, path=dest)) - return exports - except ImportError: - pass + png_files = sorted(output_dir.glob("acidslide-render-*.png"), key=_page_number) + if not png_files: + msg = "pdftoppm failed to produce PNG output" + raise RuntimeError(msg) + if expected_page_count is not None and len(png_files) != expected_page_count: + msg = ( + f"Canonical rasterizer produced {len(png_files)} pages; " + f"expected exactly {expected_page_count}" + ) + raise RuntimeError(msg) + return _normalize_exports(png_files, output_dir) - msg = "No PDF-to-PNG converter available. Install poppler-utils or pdf2image." + msg = "No PDF-to-PNG converter available. Install poppler-utils (pdftoppm)." raise RuntimeError(msg) -def _find_libreoffice() -> Path: +def find_libreoffice() -> Path: """Find the LibreOffice binary.""" candidates = [ "libreoffice", @@ -160,3 +172,221 @@ def _find_libreoffice() -> Path: msg = "LibreOffice not found. Install LibreOffice or ensure it is in PATH." raise RuntimeError(msg) + + +def _run_conversion( + command: list[str], + *, + check: bool, + env: dict[str, str] | None = None, +) -> subprocess.CompletedProcess[str]: + try: + completed = subprocess.run( + command, + capture_output=True, + text=True, + timeout=EXPORT_TIMEOUT, + env=env, + ) + except subprocess.TimeoutExpired as exc: + msg = f"Renderer timed out after {EXPORT_TIMEOUT} seconds" + raise RuntimeError(msg) from exc + except OSError as exc: + msg = f"Could not start renderer: {exc}" + raise RuntimeError(msg) from exc + + if check and completed.returncode != 0: + detail = completed.stderr.strip() or completed.stdout.strip() or "no diagnostic output" + msg = f"Renderer exited with code {completed.returncode}: {detail}" + raise RuntimeError(msg) + stderr_lines = {line.strip() for line in completed.stderr.splitlines() if line.strip()} + allowed_stderr = _ALLOWED_LIBREOFFICE_STDERR_LINES if "--convert-to" in command else set() + unexpected_stderr = sorted(stderr_lines - allowed_stderr) + if check and unexpected_stderr: + raise RuntimeError( + "Renderer emitted unclassified stderr despite a zero exit: " + + " | ".join(unexpected_stderr) + ) + return completed + + +def _libreoffice_environment(temp_root: Path) -> dict[str, str]: + """Return an isolated LibreOffice environment without changing the process. + + The frozen Docker renderer already supplies its attested Fontconfig file and + search path. Preserve that environment exactly. A local host without the + canonical configuration instead receives a one-conversion Fontconfig setup + that exposes only the benchmark font directory and a writable cache. + """ + environment = dict(os.environ) + if environment.get("FONTCONFIG_FILE"): + return environment + + benchmark_dir = resolve_benchmark_dir() + font_dir = (benchmark_dir / "fonts" / "files").resolve() + if not font_dir.is_dir() or not any(path.is_file() for path in font_dir.iterdir()): + raise RuntimeError( + f"Bundled benchmark fonts are unavailable; expected font files under {font_dir}" + ) + + fontconfig_dir = temp_root / "fontconfig" + cache_dir = fontconfig_dir / "cache" + cache_dir.mkdir(parents=True) + config_path = fontconfig_dir / "fonts.conf" + config_path.write_text( + '\n' + '\n' + "\n" + f" {_xml_text(font_dir)}\n" + f" {_xml_text(cache_dir.resolve())}\n" + " 0\n" + "\n", + encoding="utf-8", + ) + environment["FONTCONFIG_FILE"] = str(config_path.resolve()) + environment["FONTCONFIG_PATH"] = str(fontconfig_dir.resolve()) + return environment + + +def _xml_text(path: Path) -> str: + """Escape a filesystem path for use as Fontconfig XML text.""" + return str(path).replace("&", "&").replace("<", "<").replace(">", ">") + + +def _validate_pdf_geometry(pdf_path: Path, expected_page_count: int) -> None: + """Reject PDF outputs whose page count, boxes, or rotation differ from v1.""" + try: + reader = PdfReader(pdf_path, strict=True) + pages = list(reader.pages) + except Exception as exc: + raise RuntimeError(f"Canonical PDF metadata could not be parsed: {exc}") from exc + if len(pages) != expected_page_count: + raise RuntimeError( + f"Canonical PDF contains {len(pages)} pages; expected exactly {expected_page_count}" + ) + + page_references: list[tuple[int, int]] = [] + for page in pages: + reference = page.indirect_reference + if reference is None: + raise RuntimeError("Canonical PDF page has no indirect object reference") + page_references.append((reference.idnum, reference.generation)) + raw_boxes = _raw_page_boxes(pdf_path, page_references) + + expected_box = (Decimal(0), Decimal(0), PDF_WIDTH_POINTS, PDF_HEIGHT_POINTS) + for page_number, page in enumerate(pages, 1): + rotation = page.rotation + media_box, explicit_crop_box = raw_boxes[page_number - 1] + crop_box = explicit_crop_box or media_box + if rotation != 0: + raise RuntimeError( + f"Canonical PDF page {page_number} has rotation {rotation}; expected 0" + ) + if media_box != expected_box or crop_box != expected_box: + raise RuntimeError( + f"Canonical PDF page {page_number} must have MediaBox/effective CropBox " + f"{expected_box}; found MediaBox={media_box}, CropBox={crop_box}" + ) + + +def _raw_page_boxes( + pdf_path: Path, + page_references: list[tuple[int, int]], +) -> list[ + tuple[ + tuple[Decimal, Decimal, Decimal, Decimal], + tuple[Decimal, Decimal, Decimal, Decimal] | None, + ] +]: + """Read page boxes without a PDF library's floating-point normalization.""" + try: + raw = pdf_path.read_bytes() + except OSError as exc: + raise RuntimeError(f"Canonical PDF bytes could not be read: {exc}") from exc + + boxes = [] + for object_number, generation in page_references: + body = _raw_indirect_object(raw, object_number, generation) + media_box = _raw_box(body, b"MediaBox", required=True) + crop_box = _raw_box(body, b"CropBox", required=False) + assert media_box is not None + boxes.append((media_box, crop_box)) + return boxes + + +def _raw_indirect_object(raw: bytes, object_number: int, generation: int) -> bytes: + header = re.compile( + rb"(?m)^[ \t]*" + + str(object_number).encode("ascii") + + rb"[ \t]+" + + str(generation).encode("ascii") + + rb"[ \t]+obj(?:[ \t]*\r?\n|[ \t]+)" + ) + matches = list(header.finditer(raw)) + if len(matches) != 1: + raise RuntimeError( + f"Canonical PDF page object {object_number} {generation} is missing or ambiguous" + ) + start = matches[0].end() + end = raw.find(b"endobj", start) + if end < 0: + raise RuntimeError(f"Canonical PDF page object {object_number} {generation} has no endobj") + return raw[start:end] + + +def _raw_box( + object_body: bytes, + name: bytes, + *, + required: bool, +) -> tuple[Decimal, Decimal, Decimal, Decimal] | None: + pattern = re.compile( + rb"/" + + name + + rb"\b\s*\[\s*(" + + _PDF_NUMBER + + rb")\s+(" + + _PDF_NUMBER + + rb")\s+(" + + _PDF_NUMBER + + rb")\s+(" + + _PDF_NUMBER + + rb")\s*\]" + ) + matches = pattern.findall(object_body) + if not matches: + if not required: + return None + raise RuntimeError(f"Canonical PDF page has no direct /{name.decode('ascii')}") + if len(matches) != 1: + raise RuntimeError(f"Canonical PDF page has ambiguous /{name.decode('ascii')}") + try: + return tuple(Decimal(value.decode("ascii")) for value in matches[0]) # type: ignore[return-value] + except (UnicodeDecodeError, ArithmeticError) as exc: + raise RuntimeError("Canonical PDF contains an invalid page box") from exc + + +def _normalize_exports(png_files: list[Path], output_dir: Path) -> list[SlideExport]: + exports: list[SlideExport] = [] + for slide_number, png in enumerate(png_files, 1): + destination = output_dir / f"slide-{slide_number:02d}.png" + with Image.open(png) as image: + rgb = image.convert("RGB") + if rgb.size != (EXPORT_WIDTH, EXPORT_HEIGHT): + msg = ( + f"Canonical rasterizer produced {rgb.size[0]}x{rgb.size[1]} for " + f"slide {slide_number}; expected {EXPORT_WIDTH}x{EXPORT_HEIGHT}" + ) + raise RuntimeError(msg) + rgb.save(destination, "PNG", optimize=False, compress_level=9) + if png != destination: + png.unlink() + exports.append(SlideExport(slide_number=slide_number, path=destination)) + return exports + + +def _page_number(path: Path) -> int: + try: + return int(path.stem.rsplit("-", maxsplit=1)[1]) + except (IndexError, ValueError): + return 0 diff --git a/acidslide-v1/grader/acidslide/inspect_ooxml.py b/acidslide-v1/grader/acidslide/inspect_ooxml.py index aefd7cf..76424e0 100644 --- a/acidslide-v1/grader/acidslide/inspect_ooxml.py +++ b/acidslide-v1/grader/acidslide/inspect_ooxml.py @@ -5,15 +5,15 @@ import hashlib import zipfile from dataclasses import dataclass, field -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from lxml import etree +from acidslide.mce import preprocess_markup_compatibility + if TYPE_CHECKING: from pathlib import Path - pass - # OOXML namespaces NS = { "p": "http://schemas.openxmlformats.org/presentationml/2006/main", @@ -60,6 +60,7 @@ class SceneObject: table_rows: int = 0 table_cols: int = 0 is_chart: bool = False + is_picture: bool = False chart_type: str = "" field_type: str = "" # slidenum, datetime, etc. asset_hash: str = "" @@ -71,6 +72,10 @@ class SceneObject: layout_ref: str = "" master_ref: str = "" + def __post_init__(self) -> None: + if self.obj_type == "picture": + self.is_picture = True + @dataclass class SlideGraph: @@ -79,6 +84,7 @@ class SlideGraph: slide_number: int layout_name: str = "" master_name: str = "" + layout_ref: str = "" objects: list[SceneObject] = field(default_factory=list) @property @@ -101,14 +107,18 @@ class DeckGraph: layout_names: list[str] = field(default_factory=list) media_hashes: dict[str, str] = field(default_factory=dict) all_fonts: set[str] = field(default_factory=set) # all typeface refs across the package + notes_slides: set[int] = field(default_factory=set) + comment_slides: set[int] = field(default_factory=set) - def to_dict(self) -> dict: + def to_dict(self) -> dict[str, Any]: """Serialize to dict for JSON output / fixture comparison.""" return { "slide_count": len(self.slides), "master_names": self.master_names, "layout_names": self.layout_names, "media_hashes": self.media_hashes, + "notes_slides": sorted(self.notes_slides), + "comment_slides": sorted(self.comment_slides), "slides": [ { "slide_number": s.slide_number, @@ -141,8 +151,14 @@ def extract_deck_graph(pptx_path: Path) -> DeckGraph: # Parse each slide for i, part_name in enumerate(slide_parts, 1): if part_name in zf.namelist(): + has_notes, has_comments = _related_slide_content(zf, part_name, parser) + if has_notes: + deck.notes_slides.add(i) + if has_comments: + deck.comment_slides.add(i) xml_bytes = zf.read(part_name) tree = etree.fromstring(xml_bytes, parser=parser) + preprocess_markup_compatibility(tree) slide = _parse_slide(tree, i, zf, part_name, parser) deck.slides.append(slide) @@ -152,6 +168,27 @@ def extract_deck_graph(pptx_path: Path) -> DeckGraph: return deck +def _related_slide_content( + zf: zipfile.ZipFile, + part_name: str, + parser: etree.XMLParser, +) -> tuple[bool, bool]: + """Return whether a slide relationship set contains notes or comments.""" + rels_name = part_name.replace("ppt/slides/", "ppt/slides/_rels/") + ".rels" + if rels_name not in zf.namelist(): + return False, False + rels = etree.fromstring(zf.read(rels_name), parser=parser) + relationship_kinds = { + rel.get("Type", "").rsplit("/", 1)[-1].lower() + for rel in rels.iter(f"{{{NS['rel']}}}Relationship") + } + has_notes = "notesslide" in relationship_kinds + has_comments = bool( + relationship_kinds & {"comment", "comments", "moderncomment", "moderncomments"} + ) + return has_notes, has_comments + + def _extract_media_hashes(zf: zipfile.ZipFile) -> dict[str, str]: """Hash all media files in the .pptx.""" hashes = {} @@ -165,11 +202,7 @@ def _extract_media_hashes(zf: zipfile.ZipFile) -> dict[str, str]: def _extract_all_fonts(zf: zipfile.ZipFile, parser: etree.XMLParser) -> set[str]: """Scan all XML parts for typeface= attributes (slides, themes, masters, layouts).""" fonts: set[str] = set() - xml_parts = [ - n - for n in zf.namelist() - if n.startswith("ppt/") and n.endswith(".xml") - ] + xml_parts = [n for n in zf.namelist() if n.startswith("ppt/") and n.endswith(".xml")] for part in xml_parts: try: xml_bytes = zf.read(part) @@ -330,12 +363,14 @@ def _parse_shape(elem: etree._Element) -> SceneObject: obj.fill_type = _get_fill_type(elem) obj.has_shadow = _has_shadow(elem) obj.field_type = _get_field_type(elem) + obj.is_picture = _has_blip_fill(elem) return obj def _parse_picture(elem: etree._Element) -> SceneObject: """Parse a picture (pic) element.""" obj = SceneObject(obj_type="picture") + obj.is_picture = True obj.name = _get_nv_name(elem) obj.bbox = _get_bbox(elem) obj.rotation = _get_rotation(elem) @@ -405,9 +440,9 @@ def _get_nv_name(elem: etree._Element) -> str: # Try without namespace for sub in nv: if etree.QName(sub.tag).localname == "cNvPr": - return sub.get("name", "") + return str(sub.get("name", "")) else: - return cnv_pr.get("name", "") + return str(cnv_pr.get("name", "")) return "" @@ -474,7 +509,7 @@ def _get_text_runs(elem: etree._Element) -> list[TextRun]: def _get_placeholder_type(elem: etree._Element) -> str: """Get placeholder type (title, body, etc.).""" for ph in elem.iter(f"{{{NS['p']}}}ph"): - return ph.get("type", "body") + return str(ph.get("type", "body")) return "" @@ -511,6 +546,11 @@ def _has_shadow(elem: etree._Element) -> bool: return False +def _has_blip_fill(elem: etree._Element) -> bool: + """Return whether a native shape is raster-backed via DrawingML blip fill.""" + return any(etree.QName(desc.tag).localname == "blipFill" for desc in elem.iter()) + + def _get_field_type(elem: etree._Element) -> str: """Detect field type (slidenum, datetime, etc.).""" for fld in elem.iter(f"{{{NS['a']}}}fld"): @@ -519,13 +559,13 @@ def _get_field_type(elem: etree._Element) -> str: return "slidenum" if "datetime" in fld_type.lower(): return "datetime" - return fld_type + return str(fld_type) return "" -def _obj_to_dict(obj: SceneObject) -> dict: +def _obj_to_dict(obj: SceneObject) -> dict[str, Any]: """Serialize a SceneObject to dict.""" - d: dict = { + d: dict[str, Any] = { "type": obj.obj_type, "name": obj.name, "z_index": obj.z_index, @@ -542,6 +582,8 @@ def _obj_to_dict(obj: SceneObject) -> dict: d["table"] = {"rows": obj.table_rows, "cols": obj.table_cols} if obj.is_chart: d["chart_type"] = obj.chart_type + if obj.is_picture: + d["is_picture"] = True if obj.field_type: d["field_type"] = obj.field_type if obj.fill_type: diff --git a/acidslide-v1/grader/acidslide/mce.py b/acidslide-v1/grader/acidslide/mce.py new file mode 100644 index 0000000..2db91a3 --- /dev/null +++ b/acidslide-v1/grader/acidslide/mce.py @@ -0,0 +1,281 @@ +"""ECMA-376 Markup Compatibility and Extensibility preprocessing.""" + +from __future__ import annotations + +import json +import re +from copy import deepcopy +from typing import TYPE_CHECKING, Any + +from lxml import etree + +from acidslide.resources import resolve_normative_schema_file + +if TYPE_CHECKING: + from pathlib import Path + +MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006" +ALTERNATE_CONTENT = f"{{{MC_NAMESPACE}}}AlternateContent" +CHOICE = f"{{{MC_NAMESPACE}}}Choice" +FALLBACK = f"{{{MC_NAMESPACE}}}Fallback" +IGNORABLE = f"{{{MC_NAMESPACE}}}Ignorable" +MUST_UNDERSTAND = f"{{{MC_NAMESPACE}}}MustUnderstand" +PROCESS_CONTENT = f"{{{MC_NAMESPACE}}}ProcessContent" +PRESERVE_ELEMENTS = f"{{{MC_NAMESPACE}}}PreserveElements" +PRESERVE_ATTRIBUTES = f"{{{MC_NAMESPACE}}}PreserveAttributes" +MC_ATTRIBUTES = { + IGNORABLE, + MUST_UNDERSTAND, + PROCESS_CONTENT, + PRESERVE_ELEMENTS, + PRESERVE_ATTRIBUTES, +} +PREFIX = re.compile(r"^[A-Za-z_][A-Za-z0-9_.-]*$") +LOCAL_NAME = re.compile(r"^(?:[A-Za-z_][A-Za-z0-9_.-]*|\*)$") + + +class MCEProfileError(ValueError): + """Input markup is not processable under the frozen MCE profile.""" + + +def load_understood_namespaces(profile_path: Path | None = None) -> set[str]: + """Load the exact understood namespace set from the v1 profile.""" + path = resolve_normative_schema_file("mce-profile-v1.json", profile_path) + profile: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) + if profile.get("profile_id") != "acidslide-mce-profile-v1": + raise MCEProfileError(f"Unsupported MCE profile: {path}") + namespaces = profile.get("understood_namespaces") + if not isinstance(namespaces, list) or not all(isinstance(value, str) for value in namespaces): + raise MCEProfileError(f"Malformed understood_namespaces in {path}") + return set(namespaces) + + +def preprocess_markup_compatibility( + root: etree._Element, + understood_namespaces: set[str] | None = None, + *, + preserved_evidence: list[dict[str, str]] | None = None, +) -> etree._Element: + """Produce the one validation/inspection tree required by AcidSlide v1. + + Unsupported ``AlternateContent`` with no fallback, malformed QName lists, + undeclared prefixes, and unsupported ``MustUnderstand`` namespaces are + fatal. Unsupported ignorable markup is removed or has its children spliced + exactly as directed. Preserve directives record location evidence but do + not make unsupported markup visible to XSD validation or semantic scoring. + """ + understood = ( + load_understood_namespaces() if understood_namespaces is None else understood_namespaces + ) + evidence = preserved_evidence if preserved_evidence is not None else [] + _resolve_alternate_content(root, understood) + _process_element( + root, + understood, + evidence, + ignorable=frozenset(), + process_content=frozenset(), + preserve_elements=frozenset(), + preserve_attributes=frozenset(), + ) + return root + + +def _resolve_alternate_content(root: etree._Element, understood: set[str]) -> None: + while alternate_nodes := [ + node for node in root.iter(ALTERNATE_CONTENT) if node.getparent() is not None + ]: + for alternate in alternate_nodes: + _replace_alternate_content(alternate, understood) + + +def _replace_alternate_content(alternate: etree._Element, understood: set[str]) -> None: + parent = alternate.getparent() + if parent is None: + raise MCEProfileError("mc:AlternateContent cannot be the package-part root") + + choices: list[tuple[etree._Element, set[str]]] = [] + fallback: etree._Element | None = None + fallback_seen = False + for branch in alternate: + if branch.tag == CHOICE: + if fallback_seen: + raise MCEProfileError("mc:Choice cannot follow mc:Fallback") + requires = _prefix_namespaces(branch, "Requires", required=True) + choices.append((branch, requires)) + elif branch.tag == FALLBACK: + if fallback is not None: + raise MCEProfileError("mc:AlternateContent has more than one mc:Fallback") + fallback = branch + fallback_seen = True + else: + raise MCEProfileError(f"Unexpected child of mc:AlternateContent: {branch.tag}") + if not choices: + raise MCEProfileError("mc:AlternateContent has no mc:Choice") + + selected = next((branch for branch, requires in choices if requires <= understood), fallback) + if selected is None: + raise MCEProfileError( + "mc:AlternateContent has neither a supported mc:Choice nor mc:Fallback" + ) + + index = parent.index(alternate) + replacements = [deepcopy(child) for child in selected] + tail = alternate.tail + parent.remove(alternate) + for offset, replacement in enumerate(replacements): + parent.insert(index + offset, replacement) + if tail: + if replacements: + replacements[-1].tail = f"{replacements[-1].tail or ''}{tail}" + elif index: + previous = parent[index - 1] + previous.tail = f"{previous.tail or ''}{tail}" + else: + parent.text = f"{parent.text or ''}{tail}" + + +def _process_element( + element: etree._Element, + understood: set[str], + evidence: list[dict[str, str]], + *, + ignorable: frozenset[str], + process_content: frozenset[str], + preserve_elements: frozenset[str], + preserve_attributes: frozenset[str], +) -> None: + current_ignorable = ignorable | frozenset(_prefix_namespaces(element, IGNORABLE)) + must_understand = _prefix_namespaces(element, MUST_UNDERSTAND) + unsupported_must_understand = must_understand - understood + if unsupported_must_understand: + joined = ", ".join(sorted(unsupported_must_understand)) + raise MCEProfileError(f"Unsupported mc:MustUnderstand namespace(s): {joined}") + + current_process = process_content | frozenset(_qnames(element, PROCESS_CONTENT)) + current_preserve_elements = preserve_elements | frozenset(_qnames(element, PRESERVE_ELEMENTS)) + current_preserve_attributes = preserve_attributes | frozenset( + _qnames(element, PRESERVE_ATTRIBUTES) + ) + + for attribute in list(element.attrib): + attribute_name = str(attribute) + namespace = _namespace(attribute_name) + if attribute_name in MC_ATTRIBUTES: + del element.attrib[attribute] + elif namespace in current_ignorable and namespace not in understood: + if _matches(attribute_name, current_preserve_attributes): + evidence.append( + { + "kind": "attribute", + "xpath": element.getroottree().getpath(element), + "qname": attribute_name, + } + ) + del element.attrib[attribute] + + index = 0 + while index < len(element): + child = element[index] + namespace = _namespace(str(child.tag)) + if namespace in current_ignorable and namespace not in understood: + if _matches(str(child.tag), current_preserve_elements): + evidence.append( + { + "kind": "element", + "xpath": child.getroottree().getpath(child), + "qname": str(child.tag), + } + ) + if _matches(str(child.tag), current_process): + replacements = [deepcopy(grandchild) for grandchild in child] + tail = child.tail + element.remove(child) + for offset, replacement in enumerate(replacements): + element.insert(index + offset, replacement) + if tail and replacements: + replacements[-1].tail = f"{replacements[-1].tail or ''}{tail}" + for replacement in replacements: + _process_element( + replacement, + understood, + evidence, + ignorable=current_ignorable, + process_content=current_process, + preserve_elements=current_preserve_elements, + preserve_attributes=current_preserve_attributes, + ) + index += len(replacements) + continue + element.remove(child) + continue + _process_element( + child, + understood, + evidence, + ignorable=current_ignorable, + process_content=current_process, + preserve_elements=current_preserve_elements, + preserve_attributes=current_preserve_attributes, + ) + index += 1 + + +def _prefix_namespaces( + element: etree._Element, + attribute: str, + *, + required: bool = False, +) -> set[str]: + raw = element.get(attribute) + if raw is None: + if required: + raise MCEProfileError(f"Missing {attribute} on {element.tag}") + return set() + tokens = raw.split() + if required and not tokens: + raise MCEProfileError(f"Empty {attribute} on {element.tag}") + namespaces: set[str] = set() + for prefix in tokens: + if PREFIX.fullmatch(prefix) is None: + raise MCEProfileError(f"Malformed namespace prefix in {attribute}: {prefix!r}") + namespace = element.nsmap.get(prefix) + if namespace is None: + raise MCEProfileError(f"Undeclared namespace prefix in {attribute}: {prefix!r}") + namespaces.add(namespace) + return namespaces + + +def _qnames(element: etree._Element, attribute: str) -> set[str]: + raw = element.get(attribute) + if raw is None: + return set() + qnames: set[str] = set() + for token in raw.split(): + if token.count(":") != 1: + raise MCEProfileError( + f"Malformed QName in {etree.QName(attribute).localname}: {token!r}" + ) + prefix, local = token.split(":", 1) + if PREFIX.fullmatch(prefix) is None or LOCAL_NAME.fullmatch(local) is None: + raise MCEProfileError( + f"Malformed QName in {etree.QName(attribute).localname}: {token!r}" + ) + namespace = element.nsmap.get(prefix) + if namespace is None: + raise MCEProfileError( + f"Undeclared namespace prefix in {etree.QName(attribute).localname}: {prefix!r}" + ) + qnames.add(f"{{{namespace}}}{local}") + return qnames + + +def _namespace(qname: str) -> str: + return qname[1 : qname.index("}")] if qname.startswith("{") else "" + + +def _matches(qname: str, patterns: frozenset[str]) -> bool: + if qname in patterns: + return True + namespace = _namespace(qname) + return f"{{{namespace}}}*" in patterns diff --git a/acidslide-v1/grader/acidslide/models.py b/acidslide-v1/grader/acidslide/models.py index 1767653..6bd76eb 100644 --- a/acidslide-v1/grader/acidslide/models.py +++ b/acidslide-v1/grader/acidslide/models.py @@ -2,14 +2,26 @@ from __future__ import annotations +import hashlib import json -from dataclasses import dataclass, field +from dataclasses import asdict, dataclass, field, fields from enum import StrEnum -from typing import TYPE_CHECKING +from html import escape +from typing import TYPE_CHECKING, Any, cast +from uuid import UUID + +import rfc8785 if TYPE_CHECKING: + from collections.abc import Mapping from pathlib import Path +VERIFICATION_SCOPE = "artifact_conformance" +HOSTED_VERIFICATION_LABEL = "grading-verified artifact score; generation-attested" +LOCAL_VERIFICATION_LABEL = "local artifact score; self-reported" +REFERENCE_CONTROL_LABEL = "grading-verified reference control; no generation attribution" +BASELINE_CONTROL_LABEL = "grading-verified baseline control; not a leaderboard result" + class Severity(StrEnum): CRITICAL = "critical" @@ -30,6 +42,30 @@ class Propagation(StrEnum): ZERO_AFFECTED_SLIDES = "zero_affected_slides" +class GradingMode(StrEnum): + LOCAL = "local" + HOSTED = "hosted" + + +class RunKind(StrEnum): + SUBMISSION = "submission" + REFERENCE_CONTROL = "reference_control" + BASELINE_CONTROL = "baseline_control" + + +class GoldDuplicateCheck(StrEnum): + CLEAR = "clear" + BYTE_MATCH = "byte_match" + CANONICAL_MATCH = "canonical_match" + INCOMPLETE = "incomplete" + + +class DisqualificationState(StrEnum): + NONE = "none" + COMPLETED_INELIGIBLE = "completed_ineligible" + NON_OFFICIAL_LOCAL = "non_official_local" + + @dataclass class QuarantineResult: passed: bool @@ -46,6 +82,7 @@ class QuarantineResult: @dataclass class SchemaValidationResult: valid: bool + performed: bool = True violations: list[str] = field(default_factory=list) @@ -76,14 +113,283 @@ class ChecklistItemResult: severity: Severity source_of_truth: SourceOfTruth details: str = "" + assertion_id: str = "" + weight: int = 0 + outcome_code: str = "failed" + tier_affected_slides: list[int] = field(default_factory=list) + + def as_dict(self) -> dict[str, Any]: + return { + "id": self.id, + "assertion_id": self.assertion_id, + "passed": self.passed, + "severity": self.severity.value, + "weight": self.weight, + "source_of_truth": self.source_of_truth.value, + "outcome_code": self.outcome_code, + "tier_affected_slides": sorted(set(self.tier_affected_slides)), + "details": self.details, + } + + +@dataclass(frozen=True) +class AntiCheatFlag: + rule_id: str + disposition: str + affected_slides: tuple[int, ...] + tier_affected_slides: tuple[int, ...] + outcome_code: str = "triggered" + details: str = "" + + def as_dict(self) -> dict[str, Any]: + result: dict[str, Any] = { + "rule_id": self.rule_id, + "disposition": self.disposition, + "affected_slides": sorted(set(self.affected_slides)), + "tier_affected_slides": sorted(set(self.tier_affected_slides)), + "outcome_code": self.outcome_code, + } + if self.details: + result["details"] = self.details + return result + + +@dataclass(frozen=True) +class StableError: + code: str + part: str | None = None + location: str | None = None + details: str = "" + + def as_dict(self) -> dict[str, Any]: + result: dict[str, Any] = { + "code": self.code, + "part": self.part, + "location": self.location, + } + if self.details: + result["details"] = self.details + return result + + +@dataclass(frozen=True) +class ArtifactReportContext: + """Caller-supplied identities that the grader must never invent.""" + + grading_mode: GradingMode + run_kind: RunKind + targeted_tier: int + prompt_variant: str + generation_seed: str | None + grader_package_sha256: str + oci_image_digest: str + prompt_bundle_sha256: str + scored_assertion_inventory_sha256: str + checklist_bundle_sha256: str + schema_bundle_sha256: str + schema_root_map_sha256: str + mce_profile_sha256: str + asset_manifest_sha256: str + font_manifest_sha256: str + canonical_package_hash_profile_sha256: str + canonical_package_hash_v1: str | None + gold_duplicate_check: GoldDuplicateCheck + submission_sha256: str + mce_resolved_package_sha256: str | None + gold_submission_sha256: str + gold_mce_resolved_package_sha256: str + gold_canonical_package_hash_v1: str + environment_attestation: dict[str, Any] + assistance_class: str | None + generation_profile_sha256: str | None + attested_metrics: dict[str, Any] | None + attestation: dict[str, Any] | None + submission_id: str | None = None + campaign_id: str | None = None + campaign_slot: int | None = None + robustness_group_id: str | None = None + submitter_id: str | None = None + model_key: str | None = None + model_revision_key: str | None = None + + @classmethod + def from_dict(cls, value: Mapping[str, Any]) -> ArtifactReportContext: + """Load a context without accepting implicit or unknown provenance.""" + expected = {item.name for item in fields(cls)} + supplied = set(value) + if missing := sorted(expected - supplied): + raise ValueError(f"artifact report context is missing field(s): {', '.join(missing)}") + if unknown := sorted(supplied - expected): + raise ValueError(f"artifact report context has unknown field(s): {', '.join(unknown)}") + + payload = dict(value) + try: + payload["grading_mode"] = GradingMode(payload["grading_mode"]) + payload["run_kind"] = RunKind(payload["run_kind"]) + payload["gold_duplicate_check"] = GoldDuplicateCheck(payload["gold_duplicate_check"]) + except (TypeError, ValueError) as exc: + raise ValueError("artifact report context contains an invalid enum value") from exc + context = cls(**cast("Any", payload)) + context.validate() + return context + + def as_dict(self) -> dict[str, Any]: + """Return a complete JSON-compatible caller handoff.""" + result = asdict(self) + result["grading_mode"] = self.grading_mode.value + result["run_kind"] = self.run_kind.value + result["gold_duplicate_check"] = self.gold_duplicate_check.value + return result + + def validate(self) -> None: + if not isinstance(self.grading_mode, GradingMode): + raise ValueError("grading_mode must be local or hosted") + if not isinstance(self.run_kind, RunKind): + raise ValueError("run_kind is invalid") + if not isinstance(self.gold_duplicate_check, GoldDuplicateCheck): + raise ValueError("gold_duplicate_check is invalid") + if not isinstance(self.targeted_tier, int) or isinstance(self.targeted_tier, bool): + raise ValueError("targeted_tier must be an integer") + if self.targeted_tier not in {1, 2, 3}: + raise ValueError("targeted_tier must be 1, 2, or 3") + if not isinstance(self.prompt_variant, str) or not self.prompt_variant: + raise ValueError("prompt_variant must be non-empty") + if self.generation_seed is not None and not isinstance(self.generation_seed, str): + raise ValueError("generation_seed must be a string or null") + if self.generation_seed is not None and len(self.generation_seed.encode("utf-8")) > 256: + raise ValueError("generation_seed exceeds 256 UTF-8 bytes") + prefixed_hashes = ( + self.grader_package_sha256, + self.oci_image_digest, + self.prompt_bundle_sha256, + self.scored_assertion_inventory_sha256, + self.checklist_bundle_sha256, + self.schema_bundle_sha256, + self.schema_root_map_sha256, + self.mce_profile_sha256, + self.asset_manifest_sha256, + self.font_manifest_sha256, + self.canonical_package_hash_profile_sha256, + self.submission_sha256, + self.gold_submission_sha256, + self.gold_mce_resolved_package_sha256, + self.gold_canonical_package_hash_v1, + ) + optional_hashes = ( + self.canonical_package_hash_v1, + self.mce_resolved_package_sha256, + self.generation_profile_sha256, + ) + if any( + not isinstance(value, str) or not _is_prefixed_sha256(value) + for value in prefixed_hashes + ): + raise ValueError("artifact report context contains a non-canonical SHA-256") + if any( + value is not None and (not isinstance(value, str) or not _is_prefixed_sha256(value)) + for value in optional_hashes + ): + raise ValueError("artifact report context contains a non-canonical optional SHA-256") + if not isinstance(self.environment_attestation, dict): + raise ValueError("environment_attestation must be an object") + if self.assistance_class is not None and not isinstance(self.assistance_class, str): + raise ValueError("assistance_class must be a string or null") + if self.attested_metrics is not None and not isinstance(self.attested_metrics, dict): + raise ValueError("attested_metrics must be an object or null") + if self.attestation is not None and not isinstance(self.attestation, dict): + raise ValueError("attestation must be an object or null") + identifier_fields = ( + ("submission_id", self.submission_id), + ("campaign_id", self.campaign_id), + ("robustness_group_id", self.robustness_group_id), + ("submitter_id", self.submitter_id), + ("model_key", self.model_key), + ("model_revision_key", self.model_revision_key), + ) + for name, value in identifier_fields: + if value is not None and (not isinstance(value, str) or not _is_canonical_uuid(value)): + raise ValueError(f"{name} must be a canonical UUID or null") + if self.campaign_slot is not None and ( + not isinstance(self.campaign_slot, int) + or isinstance(self.campaign_slot, bool) + or self.campaign_slot not in {1, 2, 3} + ): + raise ValueError("campaign_slot must be 1, 2, 3, or null") + if self.grading_mode is GradingMode.LOCAL: + local_identifiers = ( + self.submission_id, + self.campaign_id, + self.campaign_slot, + self.robustness_group_id, + self.submitter_id, + self.model_key, + self.model_revision_key, + ) + if any(value is not None for value in local_identifiers): + raise ValueError("local report context cannot carry hosted identifiers") + if self.run_kind is not RunKind.SUBMISSION: + raise ValueError("local report context supports submission runs only") + if self.assistance_class not in {"unassisted", "human-assisted"}: + raise ValueError("local submission requires an assistance_class") + if self.attested_metrics is None or self.attestation is None: + raise ValueError("local submission requires attested generation metadata") + if self.grading_mode is GradingMode.HOSTED and self.run_kind is RunKind.SUBMISSION: + required_hosted = ( + self.submission_id, + self.campaign_id, + self.campaign_slot, + self.submitter_id, + self.model_key, + self.model_revision_key, + self.assistance_class, + self.generation_profile_sha256, + self.attested_metrics, + self.attestation, + ) + if any(value is None for value in required_hosted): + raise ValueError("hosted submission report context is incomplete") + if self.run_kind is not RunKind.SUBMISSION and self.grading_mode is not GradingMode.HOSTED: + raise ValueError("control report context must use hosted grading_mode") + if self.run_kind is not RunKind.SUBMISSION and any( + value is not None + for value in ( + self.submission_id, + self.campaign_id, + self.campaign_slot, + self.robustness_group_id, + self.submitter_id, + self.model_key, + self.model_revision_key, + self.assistance_class, + self.generation_profile_sha256, + self.attested_metrics, + self.attestation, + ) + ): + raise ValueError("control report context contains submission-only metadata") + + +def _is_prefixed_sha256(value: str) -> bool: + return ( + len(value) == 71 + and value.startswith("sha256:") + and all(character in "0123456789abcdef" for character in value[7:]) + ) + + +def _is_canonical_uuid(value: str) -> bool: + try: + return str(UUID(value)) == value + except ValueError: + return False @dataclass class SlideResult: slide_number: int tier: int - visual_ssim: float - visual_pixel_exact: bool + visual_ssim: float | None + visual_pixel_exact: bool | None items: list[ChecklistItemResult] = field(default_factory=list) @property @@ -99,42 +405,264 @@ def total_items(self) -> int: class GradeReport: benchmark_version: str grader_version: str - environment_hash: str - submission: str + scoring_cohort_id: str + scoring_manifest_sha256: str + grader_source_tree_sha256: str + environment_attestation_sha256: str + grader_package_sha256: str + oci_image_digest: str + prompt_bundle_sha256: str + scored_assertion_inventory_sha256: str + checklist_bundle_sha256: str + schema_bundle_sha256: str + schema_root_map_sha256: str + mce_profile_sha256: str + asset_manifest_sha256: str + font_manifest_sha256: str + grading_mode: GradingMode + run_kind: RunKind + canonical_package_hash_profile_sha256: str + canonical_package_hash_v1: str | None + gold_duplicate_check: GoldDuplicateCheck + generation_seed: str | None + submission_id: str | None + campaign_id: str | None + campaign_slot: int | None + robustness_group_id: str | None + submitter_id: str | None + model_key: str | None + model_revision_key: str | None + targeted_tier: int + prompt_variant: str + assistance_class: str | None + generation_profile_sha256: str | None + submission_sha256: str + mce_resolved_package_sha256: str | None + gold_submission_sha256: str + gold_mce_resolved_package_sha256: str + gold_canonical_package_hash_v1: str schema_valid: bool + schema_validation_performed: bool + visual_verification_performed: bool + verification_complete: bool + scoring_completed: bool + disqualification_state: DisqualificationState + ineligibility_reasons: list[str] repair_triggered: bool - fidelity_score: float + grading_duration_seconds: float + fidelity_score: float | None + campaign_contribution: float passed_items: int total_items: int deck_passed: bool eligible: bool - tier_scores: dict[str, dict] + tier_scores: dict[str, dict[str, int | float] | None] slides: list[SlideResult] = field(default_factory=list) deck_items: list[ChecklistItemResult] = field(default_factory=list) - anti_cheat_flags: list[str] = field(default_factory=list) - verified_metrics: dict = field(default_factory=dict) - attested_metrics: dict = field(default_factory=dict) + anti_cheat_flags: list[AntiCheatFlag] = field(default_factory=list) + schema_violations: list[StableError] = field(default_factory=list) + verification_errors: list[StableError] = field(default_factory=list) + environment_attestation: dict[str, Any] = field(default_factory=dict) + verified_metrics: dict[str, bool | int | float | str] = field(default_factory=dict) + attested_metrics: dict[str, Any] | None = None + attestation: dict[str, Any] | None = None + + @property + def verification_label(self) -> str: + if self.run_kind is RunKind.REFERENCE_CONTROL: + return REFERENCE_CONTROL_LABEL + if self.run_kind is RunKind.BASELINE_CONTROL: + return BASELINE_CONTROL_LABEL + if self.grading_mode is GradingMode.LOCAL: + return LOCAL_VERIFICATION_LABEL + return HOSTED_VERIFICATION_LABEL def to_json(self) -> str: return json.dumps(self._to_dict(), indent=2) - def _to_dict(self) -> dict: + def semantic_projection(self) -> dict[str, Any]: + """Return the exact score-semantic projection used for compatibility.""" + + def item_outcome(item: ChecklistItemResult) -> dict[str, Any]: + return { + "id": item.id, + "assertion_id": item.assertion_id, + "passed": item.passed, + "severity": item.severity.value, + "weight": item.weight, + "outcome_code": item.outcome_code, + "tier_affected_slides": sorted(set(item.tier_affected_slides)), + } + + def stable_error(error: StableError) -> dict[str, Any]: + return { + "code": error.code, + "part": error.part, + "location": error.location, + } + return { + "projection_schema_version": "1.0", + "run_kind": self.run_kind.value, + "grading_mode": self.grading_mode.value, + "targeted_tier": self.targeted_tier, + "prompt_variant": self.prompt_variant, + "schema_validation_performed": self.schema_validation_performed, + "schema_valid": self.schema_valid, + "visual_verification_performed": self.visual_verification_performed, + "verification_complete": self.verification_complete, + "scoring_completed": self.scoring_completed, + "eligible": self.eligible, + "disqualification_state": self.disqualification_state.value, + "ineligibility_reasons": sorted(set(self.ineligibility_reasons)), + "repair_triggered": self.repair_triggered, + "gold_duplicate_check": self.gold_duplicate_check.value, + "fidelity_score": self.fidelity_score, + "campaign_contribution": self.campaign_contribution, + "passed_items": self.passed_items, + "total_items": self.total_items, + "tier_scores": self.tier_scores, + "slides": [ + { + "slide": slide.slide_number, + "tier": slide.tier, + "passed_items": slide.passed_items, + "total_items": slide.total_items, + "items": [ + item_outcome(item) + for item in sorted(slide.items, key=lambda value: value.id) + ], + } + for slide in sorted(self.slides, key=lambda value: value.slide_number) + ], + "deck_items": [ + item_outcome(item) for item in sorted(self.deck_items, key=lambda value: value.id) + ], + "anti_cheat_flags": [ + { + "rule_id": flag.rule_id, + "disposition": flag.disposition, + "affected_slides": sorted(set(flag.affected_slides)), + "tier_affected_slides": sorted(set(flag.tier_affected_slides)), + } + for flag in sorted( + self.anti_cheat_flags, + key=lambda value: ( + value.rule_id, + value.disposition, + value.affected_slides, + ), + ) + ], + "schema_errors": [ + stable_error(error) + for error in sorted( + self.schema_violations, + key=lambda value: (value.code, value.part or "", value.location or ""), + ) + ], + "verification_errors": [ + stable_error(error) + for error in sorted( + self.verification_errors, + key=lambda value: (value.code, value.part or "", value.location or ""), + ) + ], + } + + @property + def score_semantic_report_sha256(self) -> str: + canonical = rfc8785.dumps(self.semantic_projection()) + return f"sha256:{hashlib.sha256(canonical).hexdigest()}" + + def _to_dict(self) -> dict[str, Any]: + payload: dict[str, Any] = { "benchmark_version": self.benchmark_version, + "grading_mode": self.grading_mode.value, + "run_kind": self.run_kind.value, + "verification_scope": VERIFICATION_SCOPE, + "verification_label": self.verification_label, "grader_version": self.grader_version, - "environment_hash": self.environment_hash, - "submission": self.submission, + "scoring_cohort_id": self.scoring_cohort_id, + "scoring_manifest_sha256": self.scoring_manifest_sha256, + "grader_source_tree_sha256": self.grader_source_tree_sha256, + "environment_attestation_sha256": self.environment_attestation_sha256, + "grader_package_sha256": self.grader_package_sha256, + "oci_image_digest": self.oci_image_digest, + "prompt_bundle_sha256": self.prompt_bundle_sha256, + "scored_assertion_inventory_sha256": self.scored_assertion_inventory_sha256, + "checklist_bundle_sha256": self.checklist_bundle_sha256, + "schema_bundle_sha256": self.schema_bundle_sha256, + "schema_root_map_sha256": self.schema_root_map_sha256, + "mce_profile_sha256": self.mce_profile_sha256, + "asset_manifest_sha256": self.asset_manifest_sha256, + "font_manifest_sha256": self.font_manifest_sha256, + "canonical_package_hash_profile_sha256": (self.canonical_package_hash_profile_sha256), + "canonical_package_hash_v1": self.canonical_package_hash_v1, + "gold_duplicate_check": self.gold_duplicate_check.value, + "generation_seed": self.generation_seed, + "submission_id": self.submission_id, + "campaign_id": self.campaign_id, + "campaign_slot": self.campaign_slot, + "robustness_group_id": self.robustness_group_id, + "submitter_id": self.submitter_id, + "model_key": self.model_key, + "model_revision_key": self.model_revision_key, + "targeted_tier": self.targeted_tier, + "prompt_variant": self.prompt_variant, + "assistance_class": self.assistance_class, + "generation_profile_sha256": self.generation_profile_sha256, + "submission_sha256": self.submission_sha256, + "mce_resolved_package_sha256": self.mce_resolved_package_sha256, + "gold_submission_sha256": self.gold_submission_sha256, + "gold_mce_resolved_package_sha256": self.gold_mce_resolved_package_sha256, + "gold_canonical_package_hash_v1": self.gold_canonical_package_hash_v1, "schema_valid": self.schema_valid, + "schema_validation_performed": self.schema_validation_performed, + "visual_verification_performed": self.visual_verification_performed, + "verification_complete": self.verification_complete, + "scoring_completed": self.scoring_completed, + "disqualification_state": self.disqualification_state.value, + "ineligibility_reasons": sorted(set(self.ineligibility_reasons)), "repair_triggered": self.repair_triggered, + "grading_duration_seconds": self.grading_duration_seconds, "fidelity_score": self.fidelity_score, + "campaign_contribution": self.campaign_contribution, "passed_items": self.passed_items, "total_items": self.total_items, "deck_passed": self.deck_passed, "eligible": self.eligible, + "score_semantic_report_sha256": self.score_semantic_report_sha256, + "environment_attestation": self.environment_attestation, "tier_scores": self.tier_scores, "verified_metrics": self.verified_metrics, "attested_metrics": self.attested_metrics, - "anti_cheat_flags": self.anti_cheat_flags, + "attestation": self.attestation, + "anti_cheat_flags": [ + flag.as_dict() + for flag in sorted( + self.anti_cheat_flags, + key=lambda value: ( + value.rule_id, + value.disposition, + value.affected_slides, + ), + ) + ], + "schema_violations": [ + error.as_dict() + for error in sorted( + self.schema_violations, + key=lambda value: (value.code, value.part or "", value.location or ""), + ) + ], + "verification_errors": [ + error.as_dict() + for error in sorted( + self.verification_errors, + key=lambda value: (value.code, value.part or "", value.location or ""), + ) + ], "slides": [ { "slide": s.slide_number, @@ -143,40 +671,101 @@ def _to_dict(self) -> dict: "visual_pixel_exact": s.visual_pixel_exact, "passed_items": s.passed_items, "total_items": s.total_items, - "items": [ - { - "id": i.id, - "passed": i.passed, - "severity": i.severity.value, - "source_of_truth": i.source_of_truth.value, - "details": i.details, - } - for i in s.items - ], + "items": [i.as_dict() for i in sorted(s.items, key=lambda item: item.id)], } - for s in self.slides + for s in sorted(self.slides, key=lambda slide: slide.slide_number) ], "deck_items": [ - { - "id": i.id, - "passed": i.passed, - "severity": i.severity.value, - "source_of_truth": i.source_of_truth.value, - "details": i.details, - } - for i in self.deck_items + item.as_dict() for item in sorted(self.deck_items, key=lambda item: item.id) ], } + return payload + + def to_html(self) -> str: + """Render a standalone, escaped HTML report.""" + status = "PASS" if self.deck_passed else "FAIL" + if not self.verification_complete: + status = "INCOMPLETE" + + error_items = "".join( + f"
  • {escape(error.code)}: {escape(error.details)}
  • " + for error in self.verification_errors + ) + errors = f"

    Verification errors

      {error_items}
    " if error_items else "" + rows: list[str] = [] + for slide in self.slides: + visual_ssim = f"{slide.visual_ssim:.4f}" if slide.visual_ssim is not None else "n/a" + rows.append( + "" + f"{slide.slide_number}" + f"{slide.tier}" + f"{visual_ssim}" + f"{slide.passed_items}/{slide.total_items}" + "" + ) + slide_rows = "".join(rows) + fidelity = f"{self.fidelity_score:.4f}" if self.fidelity_score is not None else "n/a" + return f""" + + + + + AcidSlide report — {escape(self.submission_id or "local/control")} + + + +

    AcidSlide grade report — {status}

    +

    {self.verification_label}

    +
    +
    Submission
    {escape(self.submission_id or "local/control")}
    +
    Fidelity
    {fidelity}
    +
    Items
    {self.passed_items}/{self.total_items}
    +
    Verification complete
    {str(self.verification_complete).lower()}
    +
    Leaderboard eligible
    {str(self.eligible).lower()}
    +
    Environment
    {escape(self.environment_attestation_sha256)}
    +
    + {errors} +

    Slides

    + + + {slide_rows} +
    SlideTierSSIMItems
    + + +""" def summary(self) -> str: - status = "[green]PASS[/green]" if self.deck_passed else "[red]FAIL[/red]" + if not self.verification_complete: + status = "[yellow]INCOMPLETE[/yellow]" + else: + status = "[green]PASS[/green]" if self.deck_passed else "[red]FAIL[/red]" lines = [ f"AcidSlide Grade Report — {status}", - f" Fidelity: {self.fidelity_score:.4f}", + f" Verification: {self.verification_label}", + f" Fidelity: {self.fidelity_score:.4f}" + if self.fidelity_score is not None + else " Fidelity: n/a", f" Items: {self.passed_items}/{self.total_items}", f" Schema valid: {self.schema_valid}", f" Repair triggered: {self.repair_triggered}", + f" Verification complete: {self.verification_complete}", + f" Leaderboard eligible: {self.eligible}", ] if self.anti_cheat_flags: lines.append(f" Anti-cheat flags: {self.anti_cheat_flags}") + if self.schema_violations: + lines.append(f" Schema violations: {len(self.schema_violations)}") + if self.verification_errors: + lines.append(" Verification errors:") + lines.extend( + f" - {error.code}: {error.details}" for error in self.verification_errors + ) return "\n".join(lines) diff --git a/acidslide-v1/grader/acidslide/mutation_fixtures.py b/acidslide-v1/grader/acidslide/mutation_fixtures.py new file mode 100644 index 0000000..152fd06 --- /dev/null +++ b/acidslide-v1/grader/acidslide/mutation_fixtures.py @@ -0,0 +1,557 @@ +"""Deterministic operator-level positive and single-fault mutation fixtures. + +These generated fixtures prove that the configured evaluator operator can pass +and can detect one isolated fault. They are not independent prompt, reference, +or asset evidence and must not be used to freeze a checklist assertion. +""" + +from __future__ import annotations + +import hashlib +from collections import Counter +from copy import deepcopy +from dataclasses import dataclass +from typing import TYPE_CHECKING, Any + +import rfc8785 + +from acidslide.evaluate import evaluate_checklist +from acidslide.inspect_ooxml import DeckGraph, SceneObject, SlideGraph, TextRun +from acidslide.models import AntiCheatFlag, ChecklistItemResult, VisualComparisonResult + +if TYPE_CHECKING: + from acidslide.checklist import ChecklistItem + +OBJECT_SELECTORS = {"chart", "connector", "field", "group", "picture", "shape", "table"} +EVIDENCE_SCOPE = ( + "generated operator behavior only; not independent assertion provenance, review, or evidence" +) + + +@dataclass +class FixturePair: + """One passing input and the corresponding one-fault negative input.""" + + positive_deck: DeckGraph + negative_deck: DeckGraph + positive_visuals: list[VisualComparisonResult] + negative_visuals: list[VisualComparisonResult] + mutation_operator: str + changed_path: str + before: Any + after: Any + expected_negative_affected_slides: tuple[int, ...] = () + + +def build_fixture_index( + items: list[ChecklistItem], assertion_inventory: dict[str, Any] +) -> dict[str, Any]: + """Build a stable per-candidate fixture index after exact inventory alignment.""" + assertions = assertion_inventory.get("assertions", []) + if not isinstance(assertions, list): + raise ValueError("Scored-assertion inventory assertions must be an array") + assertions_by_item = { + assertion["checklist_item_id"]: assertion + for assertion in assertions + if isinstance(assertion, dict) and "checklist_item_id" in assertion + } + item_ids = {item.id for item in items} + if len(assertions_by_item) != len(assertions) or set(assertions_by_item) != item_ids: + raise ValueError( + "Checklist and scored-assertion candidate inventories do not align exactly" + ) + + entries: list[dict[str, Any]] = [] + for item in sorted(items, key=lambda candidate: candidate.id): + assertion = assertions_by_item[item.id] + if assertion.get("assertion_id") != item.assertion_id: + raise ValueError(f"Assertion identity mismatch for {item.id}") + operator, unresolved_reason = _operator_for(item) + executable = operator is not None + entries.append( + { + "checklist_item_id": item.id, + "assertion_id": item.assertion_id, + "scope": item.scope, + "slide": item.slide, + "tier": item.tier, + "verification_method": item.verification.method, + "selector": item.verification.selector, + "operator_coverage_status": "executable" if executable else "unimplemented", + "mutation_operator": operator, + "positive_fixture_id": f"fixture.{item.id}.positive" if executable else None, + "single_fault_negative_fixture_id": ( + f"fixture.{item.id}.single-fault-negative" if executable else None + ), + "mutation_expectation_id": f"mutation.{item.id}" if executable else None, + "assertion_lifecycle_state": assertion.get("lifecycle_state", "unknown"), + "assertion_evidence_status": assertion.get("evidence", {}).get("status", "unknown"), + "release_evidence_claimed": False, + "unresolved_reason": unresolved_reason, + } + ) + + executable_count = sum(entry["operator_coverage_status"] == "executable" for entry in entries) + evidence_complete_count = sum( + entry["assertion_evidence_status"] == "complete" for entry in entries + ) + operator_counts = Counter( + entry["mutation_operator"] for entry in entries if entry["mutation_operator"] is not None + ) + return { + "schema_version": "1.0", + "fixture_index_id": "acidslide-generated-mutation-fixture-index-v1", + "evidence_scope": EVIDENCE_SCOPE, + "source_inventory_id": assertion_inventory.get("inventory_id"), + "candidate_contract_sha256": _candidate_contract_sha256(items), + "summary": { + "candidate_items": len(entries), + "executable_items": executable_count, + "unimplemented_items": len(entries) - executable_count, + "generated_positive_fixtures": executable_count, + "generated_single_fault_negative_fixtures": executable_count, + "generated_mutation_expectations": executable_count, + "assertion_evidence_complete": evidence_complete_count, + "assertion_evidence_pending_or_unknown": len(entries) - evidence_complete_count, + "operator_counts": dict(sorted(operator_counts.items())), + }, + "entries": entries, + } + + +def build_mutation_expectations(fixture_index: dict[str, Any]) -> dict[str, Any]: + """Build stable expectations for every executable generated mutation.""" + expectations: list[dict[str, Any]] = [] + unresolved: list[dict[str, str]] = [] + for entry in fixture_index["entries"]: + if entry["operator_coverage_status"] != "executable": + unresolved.append( + { + "checklist_item_id": entry["checklist_item_id"], + "reason": entry["unresolved_reason"], + } + ) + continue + expectations.append( + { + "mutation_expectation_id": entry["mutation_expectation_id"], + "checklist_item_id": entry["checklist_item_id"], + "assertion_id": entry["assertion_id"], + "mutation_operator": entry["mutation_operator"], + "fault_count": 1, + "positive_expected_outcome": "passed", + "negative_expected_outcome": "failed", + "expected_failed_item_ids": [entry["checklist_item_id"]], + "release_evidence_claimed": False, + } + ) + return { + "schema_version": "1.0", + "expectation_set_id": "acidslide-generated-mutation-expectations-v1", + "evidence_scope": EVIDENCE_SCOPE, + "fixture_index_id": fixture_index["fixture_index_id"], + "summary": { + "expectations": len(expectations), + "single_fault_expectations": len(expectations), + "unimplemented": len(unresolved), + }, + "expectations": expectations, + "unresolved": unresolved, + } + + +def execute_fixture_matrix( + items: list[ChecklistItem], fixture_index: dict[str, Any] +) -> dict[str, Any]: + """Materialize and execute every indexed fixture pair through the evaluator.""" + items_by_id = {item.id: item for item in items} + results: list[dict[str, Any]] = [] + skipped: list[dict[str, str]] = [] + for entry in fixture_index["entries"]: + item_id = entry["checklist_item_id"] + if entry["operator_coverage_status"] != "executable": + skipped.append({"checklist_item_id": item_id, "reason": entry["unresolved_reason"]}) + continue + item = items_by_id[item_id] + pair = _generate_pair(item) + positive_result, positive_flags = _evaluate_single( + item, pair.positive_deck, pair.positive_visuals + ) + negative_result, negative_flags = _evaluate_single( + item, pair.negative_deck, pair.negative_visuals + ) + actual_affected = _affected_slides(negative_flags) + killed = ( + positive_result.passed + and not negative_result.passed + and actual_affected == pair.expected_negative_affected_slides + ) + results.append( + { + "checklist_item_id": item_id, + "mutation_expectation_id": entry["mutation_expectation_id"], + "mutation_operator": pair.mutation_operator, + "changed_path": pair.changed_path, + "before": pair.before, + "after": pair.after, + "positive_passed": positive_result.passed, + "negative_passed": negative_result.passed, + "expected_negative_affected_slides": list(pair.expected_negative_affected_slides), + "actual_negative_affected_slides": list(actual_affected), + "mutant_killed": killed, + } + ) + + killed_count = sum(result["mutant_killed"] for result in results) + return { + "schema_version": "1.0", + "execution_report_id": "acidslide-generated-mutation-execution-v1", + "evidence_scope": EVIDENCE_SCOPE, + "fixture_index_id": fixture_index["fixture_index_id"], + "summary": { + "candidate_items": len(fixture_index["entries"]), + "executed_positive_fixtures": len(results), + "executed_single_fault_negative_fixtures": len(results), + "killed_mutants": killed_count, + "survived_mutants": len(results) - killed_count, + "unimplemented_items": len(skipped), + "assertion_evidence_completed_by_this_run": 0, + }, + "results": results, + "unimplemented": skipped, + } + + +def _operator_for(item: ChecklistItem) -> tuple[str | None, str | None]: + method = item.verification.method + selector = item.verification.selector + if item.scope == "slide" and method == "object_compare" and selector in OBJECT_SELECTORS: + return f"decrement-{selector}-count", None + mapping = { + ("slide", "text_match", "slide_text"): "replace-required-text", + ("slide", "hash_match", "approved_asset"): "replace-approved-asset-hash", + ("slide", "layout_check", "placeholder"): "remove-required-placeholder", + ("slide", "layout_check", "master_ref"): "clear-layout-reference", + ("slide", "anti_cheat", "font_policy"): "substitute-non-bundled-font", + ("slide", "visual_ssim", "full_slide"): "lower-ssim-below-threshold", + ("deck", "object_compare", "slide_count"): "change-exact-slide-count", + ("deck", "layout_check", "master_count"): "decrement-master-count", + ("deck", "layout_check", "layout_count"): "decrement-layout-count", + ("deck", "anti_cheat", "font_policy"): "substitute-non-bundled-font", + ("deck", "anti_cheat", "no_notes"): "add-speaker-notes-relationship", + ("deck", "hash_match", "asset_manifest"): "replace-one-approved-asset-hash", + ("deck", "visual_ssim", "all_slides"): "lower-one-slide-ssim", + } + operator = mapping.get((item.scope, method, selector)) + if operator is None: + return None, f"No executable fixture operator for {item.scope}:{method}:{selector}" + return operator, None + + +def _generate_pair(item: ChecklistItem) -> FixturePair: + operator, unresolved = _operator_for(item) + if operator is None: + raise ValueError(unresolved) + if item.scope == "slide": + return _generate_slide_pair(item, operator) + return _generate_deck_pair(item, operator) + + +def _generate_slide_pair(item: ChecklistItem, operator: str) -> FixturePair: + slide_number = item.slide or 1 + slide = SlideGraph(slide_number=slide_number) + positive = DeckGraph(slides=[slide], master_names=["Fixture Master"], layout_names=["Fixture"]) + visuals: list[VisualComparisonResult] = [] + changed_path = f"slides[{slide_number}]" + before: Any = None + after: Any = None + + if item.verification.method == "object_compare": + count = _required_count(item) + slide.objects = [_object_for_selector(item.verification.selector) for _ in range(count)] + negative = deepcopy(positive) + negative.slides[0].objects.pop() + changed_path += f".objects[{count - 1}]" + before, after = "present", "removed" + elif item.verification.method == "text_match": + expected = item.verification.expectation.get("contains") + if not isinstance(expected, str) or not expected: + raise ValueError(f"Unsupported text expectation for {item.id}") + slide.objects = [SceneObject(obj_type="shape", text_runs=[TextRun(text=expected)])] + negative = deepcopy(positive) + negative.slides[0].objects[0].text_runs[0].text = "single-fault replacement" + changed_path += ".objects[0].text_runs[0].text" + before, after = expected, "single-fault replacement" + elif item.verification.method == "hash_match": + expected_hash = item.verification.expectation.get("sha256") + if not isinstance(expected_hash, str) or not expected_hash: + raise ValueError(f"Unsupported asset hash expectation for {item.id}") + slide.objects = [SceneObject(obj_type="picture")] + positive.media_hashes = {"ppt/media/fixture.bin": expected_hash} + negative = deepcopy(positive) + negative.media_hashes["ppt/media/fixture.bin"] = "0" * 64 + changed_path = "media_hashes[ppt/media/fixture.bin]" + before, after = expected_hash, "0" * 64 + elif item.verification.method == "layout_check" and item.verification.selector == "placeholder": + count = max(1, int(item.verification.expectation.get("min_count", 1))) + placeholder_type = str(item.verification.expectation.get("placeholder_type", "title")) + slide.objects = [ + SceneObject(obj_type="shape", placeholder_type=placeholder_type) for _ in range(count) + ] + negative = deepcopy(positive) + negative.slides[0].objects.pop() + changed_path += f".objects[{count - 1}]" + before, after = "required placeholder", "removed" + elif item.verification.method == "layout_check": + slide.layout_ref = "../slideLayouts/slideLayout1.xml" + negative = deepcopy(positive) + negative.slides[0].layout_ref = "" + changed_path += ".layout_ref" + before, after = slide.layout_ref, "" + elif item.verification.method == "anti_cheat": + slide.objects = [ + SceneObject( + obj_type="shape", + text_runs=[TextRun(text="fixture", font_family="Carlito")], + ) + ] + negative = deepcopy(positive) + negative.slides[0].objects[0].text_runs[0].font_family = "Arial" + changed_path += ".objects[0].text_runs[0].font_family" + before, after = "Carlito", "Arial" + elif item.verification.method == "visual_ssim": + threshold = float(item.verification.expectation.get("min_ssim", 0.9999)) + visuals = [VisualComparisonResult(slide_number, 1.0, True)] + negative = deepcopy(positive) + negative_visuals = [ + VisualComparisonResult(slide_number, max(0.0, threshold - 0.0001), False) + ] + return FixturePair( + positive, + negative, + visuals, + negative_visuals, + operator, + f"visual_results[{slide_number}].ssim", + 1.0, + negative_visuals[0].ssim, + ) + else: + raise ValueError(f"Unsupported slide fixture operator for {item.id}") + + affected = (slide_number,) if item.failure_mode.automatic_fail_if else () + return FixturePair( + positive, + negative, + visuals, + deepcopy(visuals), + operator, + changed_path, + before, + after, + affected, + ) + + +def _generate_deck_pair(item: ChecklistItem, operator: str) -> FixturePair: + expectation = item.verification.expectation + visuals: list[VisualComparisonResult] = [] + before: Any + after: Any + if operator == "change-exact-slide-count": + count = int(expectation.get("exact_count", 20)) + positive = DeckGraph(slides=[SlideGraph(number) for number in range(1, count + 1)]) + negative = deepcopy(positive) + if count: + negative.slides.pop() + before, after = count, count - 1 + else: + negative.slides.append(SlideGraph(1)) + before, after = 0, 1 + changed_path = "slides.length" + elif operator in {"decrement-master-count", "decrement-layout-count"}: + count = max(1, int(expectation.get("min_count", 1))) + positive = DeckGraph(slides=[SlideGraph(1)]) + attribute = "master_names" if operator == "decrement-master-count" else "layout_names" + setattr(positive, attribute, [f"Fixture {index}" for index in range(count)]) + negative = deepcopy(positive) + getattr(negative, attribute).pop() + changed_path = f"{attribute}.length" + before, after = count, count - 1 + elif operator == "substitute-non-bundled-font": + positive = DeckGraph( + slides=[ + SlideGraph( + 1, + objects=[ + SceneObject( + obj_type="shape", + text_runs=[TextRun(text="one", font_family="Carlito")], + ) + ], + ), + SlideGraph( + 2, + objects=[ + SceneObject( + obj_type="shape", + text_runs=[TextRun(text="two", font_family="Noto Sans")], + ) + ], + ), + ] + ) + negative = deepcopy(positive) + negative.slides[1].objects[0].text_runs[0].font_family = "Arial" + changed_path = "slides[2].objects[0].text_runs[0].font_family" + before, after = "Noto Sans", "Arial" + return FixturePair( + positive, + negative, + visuals, + deepcopy(visuals), + operator, + changed_path, + before, + after, + (2,), + ) + elif operator == "add-speaker-notes-relationship": + positive = DeckGraph(slides=[SlideGraph(1)]) + negative = deepcopy(positive) + negative.notes_slides.add(1) + changed_path = "notes_slides" + before, after = [], [1] + return FixturePair( + positive, + negative, + visuals, + deepcopy(visuals), + operator, + changed_path, + before, + after, + (1,), + ) + elif operator == "replace-one-approved-asset-hash": + expected_hashes = expectation.get("asset_hashes", {}) + if not isinstance(expected_hashes, dict) or not expected_hashes: + raise ValueError(f"Unsupported deck hash expectation for {item.id}") + positive = DeckGraph( + slides=[SlideGraph(1)], + media_hashes={ + f"ppt/media/{asset_id}.bin": digest + for asset_id, digest in sorted(expected_hashes.items()) + }, + ) + negative = deepcopy(positive) + first_asset = sorted(expected_hashes)[0] + key = f"ppt/media/{first_asset}.bin" + negative.media_hashes[key] = "0" * 64 + changed_path = f"media_hashes[{key}]" + before, after = positive.media_hashes[key], "0" * 64 + elif operator == "lower-one-slide-ssim": + threshold = float(expectation.get("min_ssim", 0.9999)) + positive = DeckGraph(slides=[SlideGraph(1), SlideGraph(2)]) + negative = deepcopy(positive) + visuals = [VisualComparisonResult(1, 1.0, True), VisualComparisonResult(2, 1.0, True)] + negative_visuals = deepcopy(visuals) + negative_visuals[1].ssim = max(0.0, threshold - 0.0001) + negative_visuals[1].pixel_exact = False + return FixturePair( + positive, + negative, + visuals, + negative_visuals, + operator, + "visual_results[2].ssim", + 1.0, + negative_visuals[1].ssim, + ) + else: + raise ValueError(f"Unsupported deck fixture operator for {item.id}") + + return FixturePair( + positive, + negative, + visuals, + deepcopy(visuals), + operator, + changed_path, + before, + after, + ) + + +def _required_count(item: ChecklistItem) -> int: + expectation = item.verification.expectation + if "exact_count" in expectation: + count = int(expectation["exact_count"]) + else: + count = int(expectation.get("min_count", 1 if expectation.get("required") else 0)) + if count < 1: + raise ValueError(f"Cannot generate a decrement mutation for zero-count item {item.id}") + return count + + +def _object_for_selector(selector: str) -> SceneObject: + if selector == "chart": + return SceneObject(obj_type="chart", is_chart=True) + if selector == "field": + return SceneObject(obj_type="shape", field_type="slidenum") + if selector == "picture": + return SceneObject(obj_type="picture") + if selector == "table": + return SceneObject(obj_type="table", is_table=True) + return SceneObject(obj_type=selector) + + +def _evaluate_single( + item: ChecklistItem, + deck: DeckGraph, + visuals: list[VisualComparisonResult], +) -> tuple[ChecklistItemResult, list[AntiCheatFlag]]: + tier_slides = [slide.slide_number for slide in deck.slides] + slide_results, deck_results, flags = evaluate_checklist( + deck, + [item], + visuals, + tier_slides=tier_slides, + ) + if item.scope == "deck": + if len(deck_results) != 1: + raise ValueError(f"Expected one deck result for {item.id}") + return deck_results[0], flags + item_results = [result for slide in slide_results for result in slide.items] + if len(item_results) != 1: + raise ValueError(f"Expected one slide result for {item.id}") + return item_results[0], flags + + +def _affected_slides(flags: list[AntiCheatFlag]) -> tuple[int, ...]: + return tuple(sorted({slide for flag in flags for slide in flag.affected_slides})) + + +def _candidate_contract_sha256(items: list[ChecklistItem]) -> str: + normalized: list[dict[str, Any]] = [ + { + "id": item.id, + "assertion_id": item.assertion_id, + "scope": item.scope, + "slide": item.slide, + "tier": item.tier, + "verification": { + "method": item.verification.method, + "selector": item.verification.selector, + "expectation": item.verification.expectation, + }, + "failure_mode": { + "automatic_fail_if": item.failure_mode.automatic_fail_if, + "propagation": item.failure_mode.propagation, + "affected_slides": item.failure_mode.affected_slides, + }, + } + for item in sorted(items, key=lambda candidate: candidate.id) + ] + payload: Any = normalized + return f"sha256:{hashlib.sha256(rfc8785.dumps(payload)).hexdigest()}" diff --git a/acidslide-v1/grader/acidslide/package_hash.py b/acidslide-v1/grader/acidslide/package_hash.py new file mode 100644 index 0000000..e493d7e --- /dev/null +++ b/acidslide-v1/grader/acidslide/package_hash.py @@ -0,0 +1,498 @@ +"""Normative AcidSlide v1 canonical OOXML package hashing.""" + +from __future__ import annotations + +import hashlib +import json +import posixpath +import struct +import unicodedata +import zipfile +from dataclasses import dataclass +from pathlib import Path, PurePosixPath +from typing import Any +from urllib.parse import unquote, urlsplit + +from lxml import etree + +from acidslide.mce import load_understood_namespaces, preprocess_markup_compatibility +from acidslide.resources import resolve_normative_schema_file + +CONTENT_TYPES = "[Content_Types].xml" +CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types" +RELATIONSHIPS_NS = "http://schemas.openxmlformats.org/package/2006/relationships" +RELATIONSHIPS_TYPE = "application/vnd.openxmlformats-package.relationships+xml" + + +class PackageHashError(ValueError): + """The package cannot be hashed under the v1 fail-closed profile.""" + + +class PackageHashProfileMismatchError(PackageHashError): + """The active Stage 0.5 profiles do not match the scoring manifest.""" + + +@dataclass(frozen=True) +class CanonicalPackageIdentity: + """Digest plus the three normative profile identities that produced it.""" + + canonical_package_sha256: str + package_hash_profile_sha256: str + mce_profile_sha256: str + schema_root_map_sha256: str + + +@dataclass(frozen=True) +class GoldCopyDecision: + """Result of comparing one submission with both published gold identities.""" + + byte_sha256: str + canonical_package_sha256: str + byte_match: bool + canonical_package_match: bool + + @property + def reason(self) -> str | None: + return "gold_artifact_copy" if self.byte_match or self.canonical_package_match else None + + +def sha256_file(path: Path) -> str: + """Return the lowercase SHA-256 hex digest of ``path``.""" + digest = hashlib.sha256() + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def canonical_package_sha256( + package_path: Path, + profile_path: Path | None = None, + *, + mce_profile_path: Path | None = None, + root_map_path: Path | None = None, +) -> str: + """Hash uncompressed parts using the published v1 binary framing. + + ZIP entry order, compression, timestamps, comments, and other container + metadata are excluded. Only the core-property element text explicitly + enumerated by the profile is normalized. + """ + return canonical_package_identity( + package_path, + profile_path, + mce_profile_path=mce_profile_path, + root_map_path=root_map_path, + ).canonical_package_sha256 + + +def canonical_package_identity( + package_path: Path, + profile_path: Path | None = None, + *, + mce_profile_path: Path | None = None, + root_map_path: Path | None = None, +) -> CanonicalPackageIdentity: + """Return the Stage 0.5-resolved package identity and profile hashes.""" + resolved_profile, profile = _load_profile(profile_path) + resolved_mce = resolve_normative_schema_file("mce-profile-v1.json", mce_profile_path) + resolved_root_map = resolve_normative_schema_file("schema-root-map-v1.json", root_map_path) + understood_namespaces = load_understood_namespaces(resolved_mce) + root_map = _load_root_map(resolved_root_map) + domain = profile["framing"]["domain_separator_utf8"].encode("utf-8") + hasher = hashlib.sha256(domain) + try: + with zipfile.ZipFile(package_path) as package: + parts = _read_parts(package) + except zipfile.BadZipFile as exc: + raise PackageHashError("Invalid ZIP structure") from exc + + content_types = _parse_content_types(parts, profile) + resolved_relationships = _validate_relationship_graph(parts, content_types, profile) + volatile = profile["volatile_xml"] + volatile_name = str(volatile["part_name"]) + for name in sorted(parts, key=lambda value: value.encode("utf-8")): + content = parts[name] + if name == volatile_name: + content = _normalize_volatile_xml(content, volatile) + elif name == CONTENT_TYPES: + content = _canonicalize_content_types(content) + elif content_types[name] == RELATIONSHIPS_TYPE: + content = _canonicalize_relationships( + content, + resolved_relationships[name], + ) + elif _is_xml_content_type(content_types[name]): + content = _canonicalize_stage_0_5_xml( + content, + name, + content_types[name], + understood_namespaces, + root_map, + ) + name_bytes = name.encode("utf-8") + hasher.update(struct.pack(">I", len(name_bytes))) + hasher.update(name_bytes) + hasher.update(struct.pack(">Q", len(content))) + hasher.update(content) + return CanonicalPackageIdentity( + canonical_package_sha256=hasher.hexdigest(), + package_hash_profile_sha256=sha256_file(resolved_profile), + mce_profile_sha256=sha256_file(resolved_mce), + schema_root_map_sha256=sha256_file(resolved_root_map), + ) + + +def detect_gold_copy( + submission_path: Path, + *, + gold_byte_sha256: str, + gold_canonical_package_sha256: str, + expected_package_hash_profile_sha256: str, + expected_mce_profile_sha256: str, + expected_schema_root_map_sha256: str, + profile_path: Path | None = None, + mce_profile_path: Path | None = None, + root_map_path: Path | None = None, +) -> GoldCopyDecision: + """Reject an exact or repacked public-gold artifact before ranking.""" + byte_digest = sha256_file(submission_path) + identity = canonical_package_identity( + submission_path, + profile_path, + mce_profile_path=mce_profile_path, + root_map_path=root_map_path, + ) + expected_profiles = { + "package-hash": _bare_sha256(expected_package_hash_profile_sha256), + "MCE": _bare_sha256(expected_mce_profile_sha256), + "schema/root-map": _bare_sha256(expected_schema_root_map_sha256), + } + actual_profiles = { + "package-hash": identity.package_hash_profile_sha256, + "MCE": identity.mce_profile_sha256, + "schema/root-map": identity.schema_root_map_sha256, + } + mismatches = [ + name for name in expected_profiles if expected_profiles[name] != actual_profiles[name] + ] + if mismatches: + raise PackageHashProfileMismatchError( + f"Canonical package hash profile mismatch: {', '.join(mismatches)}" + ) + package_digest = identity.canonical_package_sha256 + expected_byte = _bare_sha256(gold_byte_sha256) + expected_package = _bare_sha256(gold_canonical_package_sha256) + return GoldCopyDecision( + byte_sha256=byte_digest, + canonical_package_sha256=package_digest, + byte_match=byte_digest == expected_byte, + canonical_package_match=package_digest == expected_package, + ) + + +def _load_profile(explicit: Path | None) -> tuple[Path, dict[str, Any]]: + path = resolve_normative_schema_file("canonical-package-hash-v1.json", explicit) + profile: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) + if profile.get("profile_id") != "acidslide-canonical-package-hash-v1": + raise PackageHashError(f"Unsupported canonical package hash profile: {path}") + return path, profile + + +def _read_parts(package: zipfile.ZipFile) -> dict[str, bytes]: + parts: dict[str, bytes] = {} + for info in package.infolist(): + if info.is_dir(): + continue + name = info.filename + _validate_part_name(name) + if name in parts: + raise PackageHashError(f"Duplicate ZIP part name: {name}") + if info.flag_bits & 0x1: + raise PackageHashError(f"Encrypted ZIP part is prohibited: {name}") + parts[name] = package.read(info) + if not parts: + raise PackageHashError("Package contains no file parts") + return parts + + +def _validate_part_name(name: str) -> None: + if not name or "\\" in name or "\x00" in name or name.startswith("/"): + raise PackageHashError(f"Unsafe ZIP part name: {name!r}") + if unicodedata.normalize("NFC", name) != name: + raise PackageHashError(f"Non-NFC ZIP part name: {name!r}") + path = PurePosixPath(name) + if any(part in {"", ".", ".."} for part in path.parts): + raise PackageHashError(f"Unsafe ZIP part name: {name!r}") + + +def _normalize_volatile_xml(content: bytes, profile: dict[str, Any]) -> bytes: + parser = etree.XMLParser( + resolve_entities=False, + no_network=True, + dtd_validation=False, + load_dtd=False, + huge_tree=False, + remove_blank_text=False, + ) + try: + root = etree.fromstring(content, parser=parser) + except etree.XMLSyntaxError as exc: + raise PackageHashError("docProps/core.xml is not well-formed XML") from exc + expected_root = profile["required_root_qname"] + if root.tag != expected_root: + raise PackageHashError( + f"docProps/core.xml root is {root.tag!r}; expected {expected_root!r}" + ) + for qname in profile["strip_text_qnames"]: + for element in root.iter(qname): + if len(element): + raise PackageHashError(f"Volatile core property unexpectedly has children: {qname}") + element.text = "" + strip_attributes = set(profile.get("strip_attribute_qnames", [])) + for element in root.iter(): + for attribute in list(element.attrib): + if attribute in strip_attributes: + del element.attrib[attribute] + return etree.tostring(root, method="c14n", exclusive=False, with_comments=False) + + +def _parse_content_types(parts: dict[str, bytes], profile: dict[str, Any]) -> dict[str, str]: + content = parts.get(CONTENT_TYPES) + if content is None: + raise PackageHashError(f"Required OPC control part is missing: {CONTENT_TYPES}") + root = _parse_xml(content, CONTENT_TYPES) + if root.tag != f"{{{CONTENT_TYPES_NS}}}Types": + raise PackageHashError(f"Unexpected {CONTENT_TYPES} root: {root.tag!r}") + defaults: dict[str, str] = {} + overrides: dict[str, str] = {} + for child in root: + local = etree.QName(child).localname + if local == "Default" and child.tag == f"{{{CONTENT_TYPES_NS}}}Default": + extension = child.get("Extension", "").lower() + value = child.get("ContentType", "") + if not extension or not value or extension in defaults: + raise PackageHashError("Duplicate or malformed Default content type") + defaults[extension] = value + elif local == "Override" and child.tag == f"{{{CONTENT_TYPES_NS}}}Override": + part_name = child.get("PartName", "") + value = child.get("ContentType", "") + if not part_name.startswith("/") or not value: + raise PackageHashError("Malformed Override content type") + normalized = part_name[1:] + _validate_part_name(normalized) + if normalized in overrides: + raise PackageHashError(f"Duplicate Override content type: {part_name}") + overrides[normalized] = value + else: + raise PackageHashError(f"Unexpected element in {CONTENT_TYPES}: {child.tag!r}") + + accepted = set(profile["content_type_policy"]["accepted"]) + result = {CONTENT_TYPES: "application/vnd.openxmlformats-package.content-types+xml"} + for name in parts: + if name == CONTENT_TYPES: + continue + extension = name.rsplit(".", 1)[-1].lower() if "." in name else "" + content_type = overrides.get(name, defaults.get(extension)) + if content_type is None: + raise PackageHashError(f"No content type is declared for part: {name}") + if content_type not in accepted: + raise PackageHashError(f"Unknown or prohibited content type for {name}: {content_type}") + result[name] = content_type + for name in overrides: + if name not in parts: + raise PackageHashError(f"Content type override names a missing part: {name}") + return result + + +def _validate_relationship_graph( + parts: dict[str, bytes], + content_types: dict[str, str], + profile: dict[str, Any], +) -> dict[str, list[tuple[str, str, str]]]: + relationships: dict[str, list[tuple[str, str, str]]] = {} + targets_by_source: dict[str, set[str]] = {} + office_document_type = profile["reachability_policy"]["office_document_relationship_type"] + office_document_targets: list[str] = [] + for name, content_type in content_types.items(): + if content_type != RELATIONSHIPS_TYPE: + continue + source = _source_for_relationship_part(name) + records = _relationship_records(parts[name], name, source, parts) + relationships[name] = records + targets_by_source[source] = {target for _, _, target in records} + if source == "": + office_document_targets.extend( + target + for _, relationship_type, target in records + if relationship_type == office_document_type + ) + if "_rels/.rels" not in relationships: + raise PackageHashError("Required root relationship part is missing: _rels/.rels") + if len(office_document_targets) != 1: + raise PackageHashError("Root relationships must contain exactly one officeDocument target") + + reachable = {CONTENT_TYPES, "_rels/.rels"} + pending = [""] + visited_sources: set[str] = set() + while pending: + source = pending.pop() + if source in visited_sources: + continue + visited_sources.add(source) + relationship_part = _relationship_part_for_source(source) + if relationship_part in parts: + reachable.add(relationship_part) + for target in targets_by_source.get(source, set()): + if target not in reachable: + reachable.add(target) + pending.append(target) + orphaned = sorted(set(parts) - reachable) + if orphaned: + raise PackageHashError(f"Orphan OPC part(s): {', '.join(orphaned)}") + return relationships + + +def _relationship_records( + content: bytes, + part_name: str, + source: str, + parts: dict[str, bytes], +) -> list[tuple[str, str, str]]: + root = _parse_xml(content, part_name) + if root.tag != f"{{{RELATIONSHIPS_NS}}}Relationships": + raise PackageHashError(f"Unexpected relationship root in {part_name}: {root.tag!r}") + records: list[tuple[str, str, str]] = [] + identifiers: set[str] = set() + for child in root: + if child.tag != f"{{{RELATIONSHIPS_NS}}}Relationship": + raise PackageHashError(f"Unexpected relationship element in {part_name}: {child.tag!r}") + identifier = child.get("Id", "") + relationship_type = child.get("Type", "") + target = child.get("Target", "") + if not identifier or not relationship_type or not target or identifier in identifiers: + raise PackageHashError(f"Malformed or duplicate relationship in {part_name}") + identifiers.add(identifier) + if child.get("TargetMode", "Internal") != "Internal": + raise PackageHashError(f"External relationship target is prohibited in {part_name}") + resolved = _resolve_relationship_target(source, target) + if resolved not in parts: + raise PackageHashError(f"Relationship target does not exist: {part_name} -> {resolved}") + records.append((identifier, relationship_type, resolved)) + return sorted(records, key=lambda record: record[0].encode("utf-8")) + + +def _source_for_relationship_part(name: str) -> str: + if name == "_rels/.rels": + return "" + marker = "/_rels/" + if marker not in name or not name.endswith(".rels"): + raise PackageHashError(f"Invalid OPC relationship part name: {name}") + directory, filename = name.split(marker, 1) + return f"{directory}/{filename[:-5]}" + + +def _relationship_part_for_source(source: str) -> str: + if not source: + return "_rels/.rels" + directory, _, filename = source.rpartition("/") + prefix = f"{directory}/" if directory else "" + return f"{prefix}_rels/{filename}.rels" + + +def _resolve_relationship_target(source: str, target: str) -> str: + parsed = urlsplit(target) + if parsed.scheme or parsed.netloc or parsed.query or parsed.fragment: + raise PackageHashError(f"Unsupported OPC relationship target URI: {target!r}") + decoded = unquote(parsed.path) + if "\\" in decoded or "\x00" in decoded: + raise PackageHashError(f"Unsafe OPC relationship target: {target!r}") + base = posixpath.dirname(source) + resolved = posixpath.normpath(posixpath.join(base, decoded.lstrip("/"))) + _validate_part_name(resolved) + return resolved + + +def _canonicalize_content_types(content: bytes) -> bytes: + root = _parse_xml(content, CONTENT_TYPES) + children = list(root) + children.sort( + key=lambda child: ( + etree.QName(child).localname, + child.get("Extension", "").encode("utf-8"), + child.get("PartName", "").encode("utf-8"), + ) + ) + root[:] = children + return etree.tostring(root, method="c14n", exclusive=False, with_comments=False) + + +def _canonicalize_relationships( + content: bytes, + records: list[tuple[str, str, str]], +) -> bytes: + root = _parse_xml(content, "relationship part") + root.clear() + for identifier, relationship_type, target in records: + child = etree.SubElement(root, f"{{{RELATIONSHIPS_NS}}}Relationship") + child.set("Id", identifier) + child.set("Type", relationship_type) + child.set("Target", f"/{target}") + return etree.tostring(root, method="c14n", exclusive=False, with_comments=False) + + +def _canonicalize_stage_0_5_xml( + content: bytes, + name: str, + content_type: str, + understood_namespaces: set[str], + root_map: set[tuple[str, str]], +) -> bytes: + root = _parse_xml(content, name) + if name.startswith("ppt/") and name.endswith(".xml") and "/_rels/" not in name: + preprocess_markup_compatibility(root, understood_namespaces) + key = (content_type, str(root.tag)) + if key not in root_map: + raise PackageHashError( + f"Unmapped Stage 0.5 XML part {name}: content_type={content_type!r}, " + f"root={str(root.tag)!r}" + ) + return etree.tostring(root, method="c14n", exclusive=False, with_comments=False) + + +def _parse_xml(content: bytes, name: str) -> etree._Element: + if b" bool: + return content_type.endswith("+xml") or content_type in {"application/xml", "text/xml"} + + +def _load_root_map(path: Path) -> set[tuple[str, str]]: + document = json.loads(path.read_text(encoding="utf-8")) + if document.get("mapping_id") != "acidslide-schema-root-map-v1": + raise PackageHashError(f"Unsupported schema/root mapping: {path}") + keys = {(entry["content_type"], entry["root_qname"]) for entry in document["entries"]} + if len(keys) != len(document["entries"]): + raise PackageHashError(f"Duplicate entries in schema/root mapping: {path}") + return keys + + +def _bare_sha256(value: str) -> str: + bare = value.removeprefix("sha256:") + if len(bare) != 64 or any(character not in "0123456789abcdef" for character in bare): + raise ValueError(f"Invalid SHA-256 digest: {value!r}") + return bare diff --git a/acidslide-v1/grader/acidslide/pipeline.py b/acidslide-v1/grader/acidslide/pipeline.py index cad11bf..330f83a 100644 --- a/acidslide-v1/grader/acidslide/pipeline.py +++ b/acidslide-v1/grader/acidslide/pipeline.py @@ -1,24 +1,43 @@ -"""Grading pipeline — orchestrates all stages.""" +"""Grading pipeline — orchestrates all stages without overstating verification.""" from __future__ import annotations +import hashlib import json import tempfile import time from pathlib import Path +from typing import Any + +import rfc8785 from acidslide import __version__ from acidslide.checklist import load_checklist from acidslide.compare import compare_slides +from acidslide.environment import environment_details from acidslide.evaluate import compute_fidelity_score, compute_tier_scores, evaluate_checklist from acidslide.export import export_slides from acidslide.inspect_ooxml import extract_deck_graph -from acidslide.models import GradeReport +from acidslide.models import ( + AntiCheatFlag, + ArtifactReportContext, + ChecklistItemResult, + DisqualificationState, + GoldDuplicateCheck, + GradeReport, + GradingMode, + RunKind, + SchemaValidationResult, + SlideResult, + StableError, + VisualComparisonResult, +) +from acidslide.package_hash import canonical_package_identity, sha256_file +from acidslide.provenance import ScoringCohortProvenance, load_signed_release_provenance from acidslide.quarantine import quarantine_check +from acidslide.resources import resolve_benchmark_dir from acidslide.schema_validate import validate_schema -DEFAULT_BENCHMARK_DIR = Path("/opt/acidslide/benchmark") - TIER_SLIDES: dict[int, list[int]] = { 1: list(range(1, 6)), 2: list(range(1, 13)), @@ -31,110 +50,593 @@ def run_pipeline( tier: int, benchmark_dir: Path | None = None, output_format: str = "json", + artifact_dir: Path | None = None, + cohort_provenance: ScoringCohortProvenance | None = None, + artifact_context: ArtifactReportContext | None = None, ) -> GradeReport: - """Run the full grading pipeline on a submission.""" - if benchmark_dir is None: - benchmark_dir = DEFAULT_BENCHMARK_DIR - - start_time = time.monotonic() + """Run local Stages 0–6; local reports are permanently non-official.""" + resolved_benchmark_dir, effective_cohort, context = _prepare_run( + tier=tier, + output_format=output_format, + benchmark_dir=benchmark_dir, + cohort_provenance=cohort_provenance, + artifact_context=artifact_context, + ) + if context.grading_mode is not GradingMode.LOCAL: + raise ValueError("hosted runs must use run_resolved_pipeline") - # Stage 0: Quarantine qresult = quarantine_check(submission) if not qresult.passed: return _failed_report( - submission=submission.name, - reason=f"Quarantine failed: {qresult.reason}", + cohort=effective_cohort, + context=context, + reason=StableError("quarantine_failed", details=qresult.reason), + submission_file_size_bytes=qresult.file_size_bytes, ) - # Stage 0.5: Schema validation (non-blocking) + _verify_artifact_context(submission, context, resolved=False) sresult = validate_schema(submission) + return _run_scoring_stages( + submission=submission, + benchmark_dir=resolved_benchmark_dir, + tier=tier, + artifact_dir=artifact_dir, + cohort=effective_cohort, + context=context, + schema_result=sresult, + ) - # Stage 1: Export via LibreOffice - visual_results = [] - with tempfile.TemporaryDirectory() as export_dir: - export_path = Path(export_dir) - try: - export_slides(submission, export_path) - except RuntimeError: - pass # Export failure is non-fatal; structural grading continues - # Stage 2: Visual comparison - gold_exports_dir = benchmark_dir / "deck" / "exports" - if gold_exports_dir.exists() and any(gold_exports_dir.glob("slide-*.png")): - visual_results = compare_slides(export_path, gold_exports_dir) +def run_resolved_pipeline( + resolved_package: Path, + tier: int, + *, + schema_result: SchemaValidationResult, + artifact_context: ArtifactReportContext, + benchmark_dir: Path | None = None, + output_format: str = "json", + artifact_dir: Path | None = None, + cohort_provenance: ScoringCohortProvenance | None = None, +) -> GradeReport: + """Run a hosted resolved-package result without repeating Stage 0.5. + + A performed but invalid Stage 0.5 result is itself a terminal diagnostic + result. The artifact identities are still reverified before that report is + emitted, but no renderer, parser, checklist, or scoring stage is entered. + """ + resolved_benchmark_dir, effective_cohort, context = _prepare_run( + tier=tier, + output_format=output_format, + benchmark_dir=benchmark_dir, + cohort_provenance=cohort_provenance, + artifact_context=artifact_context, + ) + if context.grading_mode is not GradingMode.HOSTED: + raise ValueError("resolved-package grading requires hosted grading_mode") + _verify_artifact_context(resolved_package, context, resolved=True) + if not schema_result.performed: + raise ValueError("hosted grading requires a performed Stage 0.5 result") + if not schema_result.valid: + schema_errors = _schema_errors(schema_result.violations) + details = ( + "Stage 0.5 rejected the resolved package" + if schema_errors + else "Stage 0.5 rejected the resolved package without a stable violation record" + ) + return _failed_report( + cohort=effective_cohort, + context=context, + reason=StableError("schema_validation_failed", details=details), + submission_file_size_bytes=resolved_package.stat().st_size, + schema_result=schema_result, + schema_errors=schema_errors, + ineligibility_reasons=["schema_validation_failed"], + ) + return _run_scoring_stages( + submission=resolved_package, + benchmark_dir=resolved_benchmark_dir, + tier=tier, + artifact_dir=artifact_dir, + cohort=effective_cohort, + context=context, + schema_result=schema_result, + ) - # Stage 3: OOXML structural extraction - deck_graph = extract_deck_graph(submission) - # Stage 4: Load checklist and evaluate - checklist_dir = benchmark_dir / "checklist" - tier_slides = TIER_SLIDES.get(tier, TIER_SLIDES[3]) +def _prepare_run( + *, + tier: int, + output_format: str, + benchmark_dir: Path | None, + cohort_provenance: ScoringCohortProvenance | None, + artifact_context: ArtifactReportContext | None, +) -> tuple[Path, ScoringCohortProvenance, ArtifactReportContext]: + if tier not in TIER_SLIDES: + raise ValueError(f"Unsupported tier {tier}; expected 1, 2, or 3") + if output_format not in {"json", "html", "text"}: + raise ValueError(f"Unsupported output format: {output_format}") + if artifact_context is None: + raise ValueError("artifact_context is required; report provenance cannot be invented") + artifact_context.validate() + if artifact_context.targeted_tier != tier: + raise ValueError("artifact_context targeted_tier does not match requested tier") + + resolved_benchmark_dir = resolve_benchmark_dir(benchmark_dir) + effective_cohort = cohort_provenance or load_signed_release_provenance(resolved_benchmark_dir) + effective_cohort.validate() + attestation_bytes = rfc8785.dumps(artifact_context.environment_attestation) + actual_attestation_hash = f"sha256:{hashlib.sha256(attestation_bytes).hexdigest()}" + if actual_attestation_hash != effective_cohort.environment_attestation_sha256: + raise ValueError("environment attestation payload does not match the scoring cohort") + return resolved_benchmark_dir, effective_cohort, artifact_context - # Also load tier definition from benchmark tiers if available - tier_file = benchmark_dir / "tiers" / f"level-{tier}" / "slides.json" - if tier_file.exists(): - tier_data = json.loads(tier_file.read_text(encoding="utf-8")) - tier_slides = tier_data.get("slides", tier_slides) - checklist_items = [] - if checklist_dir.exists(): +def _verify_artifact_context( + package: Path, + context: ArtifactReportContext, + *, + resolved: bool, +) -> None: + actual_file_hash = f"sha256:{sha256_file(package)}" + expected_file_hash = ( + context.mce_resolved_package_sha256 if resolved else context.submission_sha256 + ) + if expected_file_hash is None or actual_file_hash != expected_file_hash: + raise ValueError("artifact bytes do not match the report context") + + identity = canonical_package_identity(package) + actual_profiles = { + "canonical_package_hash_profile_sha256": f"sha256:{identity.package_hash_profile_sha256}", + "mce_profile_sha256": f"sha256:{identity.mce_profile_sha256}", + "schema_root_map_sha256": f"sha256:{identity.schema_root_map_sha256}", + } + expected_profiles = { + "canonical_package_hash_profile_sha256": (context.canonical_package_hash_profile_sha256), + "mce_profile_sha256": context.mce_profile_sha256, + "schema_root_map_sha256": context.schema_root_map_sha256, + } + if actual_profiles != expected_profiles: + raise ValueError("artifact profile hashes do not match the report context") + actual_canonical = f"sha256:{identity.canonical_package_sha256}" + if actual_canonical != context.canonical_package_hash_v1: + raise ValueError("canonical package hash does not match the report context") + + byte_match = context.submission_sha256 == context.gold_submission_sha256 + canonical_match = actual_canonical == context.gold_canonical_package_hash_v1 + expected_duplicate = ( + GoldDuplicateCheck.BYTE_MATCH + if byte_match + else GoldDuplicateCheck.CANONICAL_MATCH + if canonical_match + else GoldDuplicateCheck.CLEAR + ) + if context.gold_duplicate_check is not expected_duplicate: + raise ValueError("gold duplicate outcome does not match the report context") + + +def _run_scoring_stages( + *, + submission: Path, + benchmark_dir: Path, + tier: int, + artifact_dir: Path | None, + cohort: ScoringCohortProvenance, + context: ArtifactReportContext, + schema_result: SchemaValidationResult, +) -> GradeReport: + start_time = time.monotonic() + effective_environment = environment_details() + verification_errors: list[StableError] = [] + schema_errors = _schema_errors(schema_result.violations) + if not schema_result.performed: + verification_errors.append( + StableError("schema_validation_not_performed", details="Stage 0.5 was not performed") + ) + elif not schema_result.valid and not schema_errors: + verification_errors.append( + StableError( + "schema_validation_failed", + details="Stage 0.5 failed without a stable violation record", + ) + ) + + tier_slides, tier_errors = _load_tier_slides(benchmark_dir, tier) + verification_errors.extend(tier_errors) + visual_results, visual_verification_performed, visual_errors = _run_visual_stages( + submission=submission, + benchmark_dir=benchmark_dir, + tier_slides=tier_slides, + artifact_dir=artifact_dir, + ) + visual_results = [result for result in visual_results if result.slide_number in tier_slides] + verification_errors.extend(visual_errors) + + try: + deck_graph = extract_deck_graph(submission) + except Exception as exc: + return _failed_report( + cohort=cohort, + context=context, + reason=StableError("ooxml_extraction_failed", details=str(exc)), + submission_file_size_bytes=submission.stat().st_size, + schema_result=schema_result, + schema_errors=schema_errors, + ) + + checklist_dir = benchmark_dir / "checklist" + try: checklist_items = load_checklist(checklist_dir, tier) + except (OSError, ValueError, TypeError) as exc: + checklist_items = [] + verification_errors.append(StableError("checklist_loading_failed", details=str(exc))) + if not checklist_items: + verification_errors.append(StableError("checklist_empty", location=str(checklist_dir))) slide_results, deck_item_results, anti_cheat_flags = evaluate_checklist( deck_graph=deck_graph, items=checklist_items, - visual_results=visual_results if visual_results else None, + visual_results=visual_results, tier_slides=tier_slides, ) - - # Stage 5: Scoring - fidelity, passed, total = compute_fidelity_score(slide_results, deck_item_results) - tier_scores = compute_tier_scores(slide_results, deck_item_results, tier) - - deck_passed = ( - fidelity == 1.0 - and len(anti_cheat_flags) == 0 - and not False # repair_triggered placeholder + verification_errors = _deduplicate_errors(verification_errors) + verification_complete = ( + schema_result.performed + and schema_result.valid + and visual_verification_performed + and bool(checklist_items) + and not verification_errors ) + scoring_completed = verification_complete + if scoring_completed: + raw_fidelity, passed, total = compute_fidelity_score(slide_results, deck_item_results) + fidelity: float | None = round(raw_fidelity, 4) + tier_scores = compute_tier_scores(slide_results, deck_item_results, tier) + else: + fidelity = None + passed = 0 + total = 0 + tier_scores = {"level_1": None, "level_2": None, "level_3": None} - elapsed = time.monotonic() - start_time + repair_triggered = False + disqualification_state, ineligibility_reasons = _disqualification( + context=context, + verification_complete=verification_complete, + repair_triggered=repair_triggered, + ) + eligible = ( + context.grading_mode is GradingMode.HOSTED + and context.run_kind is RunKind.SUBMISSION + and scoring_completed + and verification_complete + and context.gold_duplicate_check is GoldDuplicateCheck.CLEAR + and disqualification_state is DisqualificationState.NONE + and not repair_triggered + ) + score_affecting_flags = any( + flag.disposition in {"zero_slide", "zero_affected_slides", "reject"} + for flag in anti_cheat_flags + ) + deck_passed = bool( + scoring_completed and fidelity == 1.0 and not score_affecting_flags and not repair_triggered + ) + if context.grading_mode is GradingMode.HOSTED and context.run_kind is RunKind.SUBMISSION: + deck_passed = deck_passed and eligible + campaign_contribution = fidelity if eligible and fidelity is not None else 0.0 + elapsed = round(time.monotonic() - start_time, 2) - return GradeReport( - benchmark_version="acidslide-v1.0.0", - grader_version=__version__, - environment_hash="TODO", - submission=submission.name, - schema_valid=sresult.valid, - repair_triggered=False, - fidelity_score=round(fidelity, 4), + return _report( + cohort=cohort, + context=context, + schema_result=schema_result, + visual_verification_performed=visual_verification_performed, + verification_complete=verification_complete, + scoring_completed=scoring_completed, + disqualification_state=disqualification_state, + ineligibility_reasons=ineligibility_reasons, + repair_triggered=repair_triggered, + grading_duration_seconds=elapsed, + fidelity_score=fidelity, + campaign_contribution=campaign_contribution, passed_items=passed, total_items=total, deck_passed=deck_passed, - eligible=True, + eligible=eligible, tier_scores=tier_scores, + submission_file_size_bytes=submission.stat().st_size, + renderer_version=str(effective_environment["libreoffice"]), slides=slide_results, deck_items=deck_item_results, anti_cheat_flags=anti_cheat_flags, - verified_metrics={ - "submission_file_size_bytes": submission.stat().st_size, - "grading_duration_seconds": round(elapsed, 2), - "schema_valid": sresult.valid, - }, + schema_errors=schema_errors, + verification_errors=verification_errors, ) -def _failed_report(submission: str, reason: str) -> GradeReport: +def _disqualification( + *, + context: ArtifactReportContext, + verification_complete: bool, + repair_triggered: bool, +) -> tuple[DisqualificationState, list[str]]: + if context.grading_mode is GradingMode.LOCAL: + return DisqualificationState.NON_OFFICIAL_LOCAL, ["local_mode"] + if context.run_kind is not RunKind.SUBMISSION: + return DisqualificationState.NONE, [] + reasons: list[str] = [] + if context.gold_duplicate_check in { + GoldDuplicateCheck.BYTE_MATCH, + GoldDuplicateCheck.CANONICAL_MATCH, + }: + reasons.append("gold_artifact_copy") + elif context.gold_duplicate_check is GoldDuplicateCheck.INCOMPLETE: + reasons.append("duplicate_check_incomplete") + if repair_triggered: + reasons.append("repair_triggered") + if not verification_complete: + reasons.append("verification_incomplete") + if reasons: + return DisqualificationState.COMPLETED_INELIGIBLE, sorted(set(reasons)) + return DisqualificationState.NONE, [] + + +def _run_visual_stages( + *, + submission: Path, + benchmark_dir: Path, + tier_slides: list[int], + artifact_dir: Path | None, +) -> tuple[list[VisualComparisonResult], bool, list[StableError]]: + errors: list[StableError] = [] + results: list[VisualComparisonResult] = [] + expected_slides = set(tier_slides) + gold_exports_dir = benchmark_dir / "deck" / "exports" + gold_slides = sorted(gold_exports_dir.glob("slide-*.png")) + gold_slide_numbers = _slide_numbers(gold_slides) + + if not gold_slides: + errors.append(StableError("gold_exports_missing", location=str(gold_exports_dir))) + elif missing_gold := expected_slides - gold_slide_numbers: + errors.append(StableError("gold_exports_incomplete", details=str(sorted(missing_gold)))) + + with tempfile.TemporaryDirectory() as export_dir: + export_path = Path(export_dir) + try: + exports = export_slides( + submission, + export_path, + expected_page_count=len(tier_slides), + ) + except RuntimeError as exc: + exports = [] + errors.append(StableError("slide_export_failed", details=str(exc))) + + exported_slide_numbers = {export.slide_number for export in exports} + if missing_exports := expected_slides - exported_slide_numbers: + errors.append( + StableError("submission_exports_missing", details=str(sorted(missing_exports))) + ) + if unexpected_exports := exported_slide_numbers - expected_slides: + errors.append( + StableError( + "submission_exports_unexpected", + details=str(sorted(unexpected_exports)), + ) + ) + + if gold_slides: + try: + results = compare_slides(export_path, gold_exports_dir, artifact_dir) + except (OSError, ValueError) as exc: + errors.append(StableError("visual_comparison_failed", details=str(exc))) + + result_slide_numbers = {result.slide_number for result in results} + missing_comparisons = expected_slides - result_slide_numbers + if gold_slides and missing_comparisons: + errors.append( + StableError("visual_comparisons_missing", details=str(sorted(missing_comparisons))) + ) + + performed = not errors and expected_slides.issubset(result_slide_numbers) + return results, performed, _deduplicate_errors(errors) + + +def _load_tier_slides(benchmark_dir: Path, tier: int) -> tuple[list[int], list[StableError]]: + default = TIER_SLIDES[tier] + tier_file = benchmark_dir / "tiers" / f"level-{tier}" / "slides.json" + if not tier_file.is_file(): + return default, [StableError("tier_definition_missing", location=str(tier_file))] + + try: + raw: Any = json.loads(tier_file.read_text(encoding="utf-8")) + slides = raw["slides"] + if not isinstance(slides, list) or not slides: + raise ValueError("slides must be a non-empty list") + if any(not isinstance(slide, int) or isinstance(slide, bool) for slide in slides): + raise ValueError("slides must contain only integers") + except (OSError, json.JSONDecodeError, KeyError, TypeError, ValueError) as exc: + return default, [ + StableError("tier_definition_invalid", location=str(tier_file), details=str(exc)) + ] + return slides, [] + + +def _slide_numbers(paths: list[Path]) -> set[int]: + numbers: set[int] = set() + for path in paths: + try: + numbers.add(int(path.stem.rsplit("-", maxsplit=1)[1])) + except (IndexError, ValueError): + continue + return numbers + + +def _deduplicate_errors(errors: list[StableError]) -> list[StableError]: + unique: dict[tuple[str, str | None, str | None, str], StableError] = {} + for error in errors: + unique[(error.code, error.part, error.location, error.details)] = error + return list(unique.values()) + + +def _schema_errors(violations: list[str]) -> list[StableError]: + errors: list[StableError] = [] + for violation in violations: + prefix, separator, detail = violation.partition(":") + part = prefix if separator and ("/" in prefix or prefix.endswith(".xml")) else None + errors.append( + StableError( + "schema_violation", + part=part, + details=detail.strip() if part is not None else violation, + ) + ) + return _deduplicate_errors(errors) + + +def _report( + *, + cohort: ScoringCohortProvenance, + context: ArtifactReportContext, + schema_result: SchemaValidationResult, + visual_verification_performed: bool, + verification_complete: bool, + scoring_completed: bool, + disqualification_state: DisqualificationState, + ineligibility_reasons: list[str], + repair_triggered: bool, + grading_duration_seconds: float, + fidelity_score: float | None, + campaign_contribution: float, + passed_items: int, + total_items: int, + deck_passed: bool, + eligible: bool, + tier_scores: dict[str, dict[str, int | float] | None], + submission_file_size_bytes: int, + renderer_version: str, + slides: list[SlideResult], + deck_items: list[ChecklistItemResult], + anti_cheat_flags: list[AntiCheatFlag], + schema_errors: list[StableError], + verification_errors: list[StableError], +) -> GradeReport: return GradeReport( benchmark_version="acidslide-v1.0.0", grader_version=__version__, - environment_hash="TODO", - submission=submission, - schema_valid=False, + scoring_cohort_id=cohort.scoring_cohort_id, + scoring_manifest_sha256=cohort.scoring_manifest_sha256, + grader_source_tree_sha256=cohort.grader_source_tree_sha256, + environment_attestation_sha256=cohort.environment_attestation_sha256, + grader_package_sha256=context.grader_package_sha256, + oci_image_digest=context.oci_image_digest, + prompt_bundle_sha256=context.prompt_bundle_sha256, + scored_assertion_inventory_sha256=context.scored_assertion_inventory_sha256, + checklist_bundle_sha256=context.checklist_bundle_sha256, + schema_bundle_sha256=context.schema_bundle_sha256, + schema_root_map_sha256=context.schema_root_map_sha256, + mce_profile_sha256=context.mce_profile_sha256, + asset_manifest_sha256=context.asset_manifest_sha256, + font_manifest_sha256=context.font_manifest_sha256, + grading_mode=context.grading_mode, + run_kind=context.run_kind, + canonical_package_hash_profile_sha256=(context.canonical_package_hash_profile_sha256), + canonical_package_hash_v1=context.canonical_package_hash_v1, + gold_duplicate_check=context.gold_duplicate_check, + generation_seed=context.generation_seed, + submission_id=context.submission_id, + campaign_id=context.campaign_id, + campaign_slot=context.campaign_slot, + robustness_group_id=context.robustness_group_id, + submitter_id=context.submitter_id, + model_key=context.model_key, + model_revision_key=context.model_revision_key, + targeted_tier=context.targeted_tier, + prompt_variant=context.prompt_variant, + assistance_class=context.assistance_class, + generation_profile_sha256=context.generation_profile_sha256, + submission_sha256=context.submission_sha256, + mce_resolved_package_sha256=context.mce_resolved_package_sha256, + gold_submission_sha256=context.gold_submission_sha256, + gold_mce_resolved_package_sha256=context.gold_mce_resolved_package_sha256, + gold_canonical_package_hash_v1=context.gold_canonical_package_hash_v1, + schema_valid=schema_result.valid, + schema_validation_performed=schema_result.performed, + visual_verification_performed=visual_verification_performed, + verification_complete=verification_complete, + scoring_completed=scoring_completed, + disqualification_state=disqualification_state, + ineligibility_reasons=ineligibility_reasons, + repair_triggered=repair_triggered, + grading_duration_seconds=grading_duration_seconds, + fidelity_score=fidelity_score, + campaign_contribution=campaign_contribution, + passed_items=passed_items, + total_items=total_items, + deck_passed=deck_passed, + eligible=eligible, + tier_scores=tier_scores, + slides=slides, + deck_items=deck_items, + anti_cheat_flags=anti_cheat_flags, + schema_violations=schema_errors, + verification_errors=verification_errors, + environment_attestation=context.environment_attestation, + verified_metrics={ + "submission_file_size_bytes": submission_file_size_bytes, + "grading_duration_seconds": grading_duration_seconds, + "schema_valid": schema_result.valid, + "schema_validation_performed": schema_result.performed, + "visual_verification_performed": visual_verification_performed, + "verification_complete": verification_complete, + "renderer_version": renderer_version, + }, + attested_metrics=context.attested_metrics, + attestation=context.attestation, + ) + + +def _failed_report( + cohort: ScoringCohortProvenance, + context: ArtifactReportContext, + reason: StableError, + submission_file_size_bytes: int, + *, + schema_result: SchemaValidationResult | None = None, + schema_errors: list[StableError] | None = None, + ineligibility_reasons: list[str] | None = None, +) -> GradeReport: + effective_schema_result = schema_result or SchemaValidationResult(valid=False, performed=False) + state, reasons = _disqualification( + context=context, + verification_complete=False, + repair_triggered=False, + ) + if ineligibility_reasons is not None: + reasons = sorted(set(reasons + ineligibility_reasons)) + if context.grading_mode is GradingMode.HOSTED and context.run_kind is RunKind.SUBMISSION: + state = DisqualificationState.COMPLETED_INELIGIBLE + return _report( + cohort=cohort, + context=context, + schema_result=effective_schema_result, + visual_verification_performed=False, + verification_complete=False, + scoring_completed=False, + disqualification_state=state, + ineligibility_reasons=reasons, repair_triggered=False, - fidelity_score=0.0, + grading_duration_seconds=0.0, + fidelity_score=None, + campaign_contribution=0.0, passed_items=0, total_items=0, deck_passed=False, eligible=False, - tier_scores={}, + tier_scores={"level_1": None, "level_2": None, "level_3": None}, + submission_file_size_bytes=submission_file_size_bytes, + renderer_version="unavailable", + slides=[], + deck_items=[], + anti_cheat_flags=[], + schema_errors=schema_errors or [], + verification_errors=[reason], ) diff --git a/acidslide-v1/grader/acidslide/profile_contract.py b/acidslide-v1/grader/acidslide/profile_contract.py new file mode 100644 index 0000000..e0c4e70 --- /dev/null +++ b/acidslide-v1/grader/acidslide/profile_contract.py @@ -0,0 +1,197 @@ +"""Load and hash the normative AcidSlide render/comparison profiles.""" + +from __future__ import annotations + +import hashlib +import json +import struct +from dataclasses import dataclass +from typing import TYPE_CHECKING, Any + +from jsonschema import Draft202012Validator + +from acidslide.package_hash import sha256_file +from acidslide.resources import resolve_normative_schema_file + +if TYPE_CHECKING: + from pathlib import Path + +TREE_DOMAIN = b"AcidSlide deterministic tree hash v1\x00" + +_PROFILE_FILES = { + "export": ("export-profile-v1.json", "export-profile.schema.json"), + "png": ("png-profile-v1.json", "png-profile.schema.json"), + "ssim": ("ssim-profile-v1.json", "ssim-profile.schema.json"), +} + + +class ProfileContractError(ValueError): + """A normative profile is missing, invalid, or inconsistent.""" + + +@dataclass(frozen=True) +class RenderProfiles: + """Validated profile documents plus exact-byte content identities.""" + + export: dict[str, Any] + png: dict[str, Any] + ssim: dict[str, Any] + export_sha256: str + png_sha256: str + ssim_sha256: str + + @property + def hashes(self) -> dict[str, str]: + return { + "export_profile_sha256": self.export_sha256, + "png_profile_sha256": self.png_sha256, + "ssim_profile_sha256": self.ssim_sha256, + } + + def export_contract(self) -> dict[str, Any]: + """Return the exact environment-attestation export contract projection.""" + return { + "libreoffice_command": self.export["libreoffice_command"], + "pdftoppm_command": self.png["pdftoppm_command"], + "presentation_size_emu": self.export["presentation_size_emu"], + "allowed_page_counts": self.export["allowed_page_counts"], + "width_px": self.png["width_px"], + "height_px": self.png["height_px"], + "color_mode": self.png["color_mode"], + "reference_datetime": self.export["reference_datetime"], + "pdf_page_geometry": self.export["pdf_page_geometry"], + } + + def scoring_export(self) -> dict[str, Any]: + """Return the exact scoring-manifest export projection.""" + encoder = self.png["encoder"] + return { + "pipeline": self.export["pipeline"], + "execution_wrapper": self.export["execution_wrapper"], + "libreoffice_command": self.export["libreoffice_command"], + "pdftoppm_command": self.png["pdftoppm_command"], + "presentation_size_emu": self.export["presentation_size_emu"], + "allowed_page_counts": self.export["allowed_page_counts"], + "width_px": self.png["width_px"], + "height_px": self.png["height_px"], + "color_mode": self.png["color_mode"], + "dimension_mismatch": "fail", + "pdf_page_geometry": self.export["pdf_page_geometry"], + "renderer_diagnostics": self.export["renderer_diagnostics"], + "png_encoder": { + "implementation": encoder["implementation"], + "format": encoder["format"], + "conversion": encoder["conversion"], + "optimize": encoder["optimize"], + "compress_level": encoder["compress_level"], + }, + } + + def scoring_visual_comparison(self) -> dict[str, Any]: + """Return the exact scoring-manifest SSIM projection.""" + fields = ( + "algorithm", + "threshold", + "dtype", + "shape", + "channel_axis", + "data_range", + "win_size", + "gaussian_weights", + "use_sample_covariance", + "K1", + "K2", + "dimension_mismatch", + "pixel_exact", + ) + return {field: self.ssim[field] for field in fields} + + +def load_render_profiles(profile_dir: Path | None = None) -> RenderProfiles: + """Load all three profiles and reject a missing or schema-invalid file.""" + documents: dict[str, dict[str, Any]] = {} + hashes: dict[str, str] = {} + for kind, (profile_name, schema_name) in _PROFILE_FILES.items(): + profile_path = resolve_normative_schema_file(profile_name, profile_dir) + schema_path = resolve_normative_schema_file(schema_name, profile_dir) + try: + document = json.loads(profile_path.read_text(encoding="utf-8")) + schema = json.loads(schema_path.read_text(encoding="utf-8")) + Draft202012Validator.check_schema(schema) + except (OSError, TypeError, ValueError, json.JSONDecodeError) as exc: + raise ProfileContractError( + f"Normative {kind} profile is unreadable: {profile_path}" + ) from exc + if not isinstance(document, dict): + raise ProfileContractError(f"Normative {kind} profile must be an object") + errors = sorted( + Draft202012Validator(schema).iter_errors(document), + key=lambda error: list(error.absolute_path), + ) + if errors: + location = "/".join(str(value) for value in errors[0].absolute_path) or "" + raise ProfileContractError( + f"Normative {kind} profile is invalid at {location}: {errors[0].message}" + ) + documents[kind] = document + hashes[kind] = f"sha256:{sha256_file(profile_path)}" + return RenderProfiles( + export=documents["export"], + png=documents["png"], + ssim=documents["ssim"], + export_sha256=hashes["export"], + png_sha256=hashes["png"], + ssim_sha256=hashes["ssim"], + ) + + +def deterministic_tree_sha256(path: Path) -> str: + """Hash a release tree using the scoring-manifest v1 binary framing.""" + if not path.is_dir(): + raise FileNotFoundError(f"Required release tree is missing: {path}") + files = sorted( + ( + candidate + for candidate in path.rglob("*") + if candidate.is_file() + and candidate.name != ".DS_Store" + and "__pycache__" not in candidate.parts + and candidate.suffix != ".pyc" + ), + key=lambda candidate: candidate.relative_to(path).as_posix().encode("utf-8"), + ) + if not files: + raise ProfileContractError(f"Required release tree is empty: {path}") + digest = hashlib.sha256(TREE_DOMAIN) + for candidate in files: + relative = candidate.relative_to(path).as_posix().encode("utf-8") + digest.update(struct.pack(">I", len(relative))) + digest.update(relative) + digest.update(bytes.fromhex(sha256_file(candidate))) + return f"sha256:{digest.hexdigest()}" + + +def environment_profile_hashes(schema_dir: Path | None = None) -> dict[str, str]: + """Recompute every profile/tree hash carried by an environment attestation.""" + profiles = load_render_profiles(schema_dir) + resolved_schema_dir = resolve_normative_schema_file("mce-profile-v1.json", schema_dir).parent + return profiles.hashes | { + "json_schema_bundle_sha256": deterministic_tree_sha256(resolved_schema_dir), + "xsd_bundle_sha256": deterministic_tree_sha256( + resolved_schema_dir / "ecma-376" / "xsd-transitional" + ), + "schema_root_map_sha256": _file_sha256(resolved_schema_dir / "schema-root-map-v1.json"), + "mce_profile_sha256": _file_sha256(resolved_schema_dir / "mce-profile-v1.json"), + "scene_graph_profile_sha256": _file_sha256( + resolved_schema_dir / "scene-graph-profile-v1.json" + ), + "canonical_package_hash_profile_sha256": _file_sha256( + resolved_schema_dir / "canonical-package-hash-v1.json" + ), + } + + +def _file_sha256(path: Path) -> str: + if not path.is_file(): + raise FileNotFoundError(f"Required normative profile is missing: {path}") + return f"sha256:{sha256_file(path)}" diff --git a/acidslide-v1/grader/acidslide/provenance.py b/acidslide-v1/grader/acidslide/provenance.py new file mode 100644 index 0000000..df7856a --- /dev/null +++ b/acidslide-v1/grader/acidslide/provenance.py @@ -0,0 +1,674 @@ +"""Verification of the signed release identity carried by every grade report.""" + +from __future__ import annotations + +import base64 +import fcntl +import hashlib +import json +import os +import re +import tempfile +from contextlib import contextmanager, suppress +from dataclasses import dataclass +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import TYPE_CHECKING, Any + +import rfc8785 +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey + +from acidslide.resources import resolve_normative_schema_file +from acidslide.source_tree import ( + GraderSourceTreeError, + GraderSourceTreeIdentity, + verify_grader_source_tree, +) + +if TYPE_CHECKING: + from collections.abc import Iterator + +_PREFIXED_SHA256 = re.compile(r"^sha256:[0-9a-f]{64}$") +_KEY_ID = re.compile(r"^[a-z0-9][a-z0-9._-]{2,63}$") +_RELEASE_CHANNEL = "acidslide-v1-stable" +_DEFAULT_CLOCK_SKEW = timedelta(minutes=5) +_INDEX_FIELDS = { + "schema_version", + "release_id", + "benchmark_version", + "channel", + "issued_at", + "effective_at", + "sequence", + "previous_release_index_sha256", + "acceptance_policy", + "state", + "scoring_manifest_sha256", + "cohort_descriptor", + "scoring_cohort_id", + "signatures", +} +_SIGNATURE_FIELDS = {"algorithm", "key_id", "signature_base64"} +_KEY_FIELDS = { + "key_id", + "algorithm", + "public_key_base64", + "valid_from", + "valid_until", + "revoked_at", +} + + +class ReleaseProvenanceError(RuntimeError): + """Raised when a benchmark release identity cannot be trusted.""" + + +@dataclass(frozen=True) +class ScoringCohortProvenance: + """The exact four-field comparison identity required in every report.""" + + scoring_cohort_id: str + scoring_manifest_sha256: str + grader_source_tree_sha256: str + environment_attestation_sha256: str + + def validate(self) -> None: + for name, value in ( + ("scoring_cohort_id", self.scoring_cohort_id), + ("scoring_manifest_sha256", self.scoring_manifest_sha256), + ("grader_source_tree_sha256", self.grader_source_tree_sha256), + ("environment_attestation_sha256", self.environment_attestation_sha256), + ): + if not _PREFIXED_SHA256.fullmatch(value): + raise ReleaseProvenanceError(f"{name} is not a canonical prefixed SHA-256") + expected = derive_scoring_cohort_id( + self.scoring_manifest_sha256, + self.grader_source_tree_sha256, + self.environment_attestation_sha256, + ) + if self.scoring_cohort_id != expected: + raise ReleaseProvenanceError("scoring_cohort_id does not match its JCS descriptor") + + +@dataclass(frozen=True) +class _VerifiedReleaseIndex: + document: dict[str, Any] + sha256: str + sequence: int + issued_at: datetime + effective_at: datetime + + +def derive_scoring_cohort_id( + scoring_manifest_sha256: str, + grader_source_tree_sha256: str, + environment_attestation_sha256: str, +) -> str: + """Derive the cohort ID using the exact OpenSpec RFC 8785 descriptor.""" + descriptor = { + "schema_version": "1.0", + "scoring_manifest_sha256": scoring_manifest_sha256, + "grader_source_tree_sha256": grader_source_tree_sha256, + "environment_attestation_sha256": environment_attestation_sha256, + } + return f"sha256:{hashlib.sha256(rfc8785.dumps(descriptor)).hexdigest()}" + + +def load_signed_release_provenance( + benchmark_dir: Path, + *, + acceptance_state_path: Path | None = None, + trusted_genesis_sha256: str | None = None, + verification_time: datetime | None = None, + clock_skew: timedelta = _DEFAULT_CLOCK_SKEW, + grader_source_path: Path | None = None, + source_tree_profile_path: Path | None = None, +) -> ScoringCohortProvenance: + """Verify a complete signed release chain and persist its highest accepted head. + + A sequence-1 ``release-index.json`` remains a valid legacy chain. Later heads + require a canonical ``release-index-chain.json`` containing every index from + genesis through the exact packaged head. + """ + manifest_path = benchmark_dir / "scoring-manifest.json" + index_path = benchmark_dir / "release-index.json" + keys_path = _release_keys_path(benchmark_dir) + manifest_bytes, manifest = _load_canonical_json(manifest_path, "scoring manifest") + index_bytes, index = _load_canonical_json(index_path, "release index") + _, keyring = _load_canonical_json(keys_path, "release keyring") + indexes = _load_release_chain(benchmark_dir, index_bytes, index) + now = _verification_time(verification_time) + verified_chain = _verify_release_chain(indexes, keyring, now=now, clock_skew=clock_skew) + head = verified_chain[-1] + index = head.document + + if manifest.get("release_status") != "frozen": + raise ReleaseProvenanceError("scoring manifest is not frozen") + if index.get("state") != "active": + raise ReleaseProvenanceError("release index chain head is not active") + if index.get("benchmark_version") != manifest.get("benchmark_version"): + raise ReleaseProvenanceError("release index and scoring manifest versions differ") + + actual_manifest_hash = f"sha256:{hashlib.sha256(manifest_bytes).hexdigest()}" + if index.get("scoring_manifest_sha256") != actual_manifest_hash: + raise ReleaseProvenanceError("scoring manifest hash does not match the release index") + + descriptor = _mapping(index.get("cohort_descriptor"), "cohort descriptor") + if descriptor.get("schema_version") != "1.0": + raise ReleaseProvenanceError("unsupported cohort descriptor version") + if descriptor.get("scoring_manifest_sha256") != actual_manifest_hash: + raise ReleaseProvenanceError("cohort descriptor does not bind the scoring manifest") + + provenance = ScoringCohortProvenance( + scoring_cohort_id=_string(index.get("scoring_cohort_id"), "scoring_cohort_id"), + scoring_manifest_sha256=actual_manifest_hash, + grader_source_tree_sha256=_string( + descriptor.get("grader_source_tree_sha256"), "grader_source_tree_sha256" + ), + environment_attestation_sha256=_string( + descriptor.get("environment_attestation_sha256"), + "environment_attestation_sha256", + ), + ) + provenance.validate() + resolved_source = _resolve_grader_source(benchmark_dir, grader_source_path) + resolved_source_profile = resolve_normative_schema_file( + "grader-source-tree-profile-v1.json", source_tree_profile_path + ) + try: + source_identity = verify_grader_source_tree( + resolved_source, + benchmark_dir / "grader-source-tree-manifest.json", + resolved_source_profile, + ) + except GraderSourceTreeError as exc: + raise ReleaseProvenanceError(str(exc)) from exc + _validate_source_tree_bindings(manifest, provenance, source_identity) + _accept_release_head( + verified_chain, + acceptance_state_path or _default_acceptance_state_path(), + trusted_genesis_sha256=trusted_genesis_sha256 + or os.getenv("ACIDSLIDE_TRUSTED_GENESIS_SHA256"), + ) + return provenance + + +def _resolve_grader_source(benchmark_dir: Path, explicit: Path | None) -> Path: + configured = explicit + if configured is None: + environment_path = os.getenv("ACIDSLIDE_GRADER_SOURCE_PATH") + configured = Path(environment_path).expanduser() if environment_path else None + if configured is not None: + return configured + candidates = ( + benchmark_dir.parent / "grader", + benchmark_dir / "grader-source", + benchmark_dir / "grader-source-tree.tar", + ) + existing = [candidate for candidate in candidates if candidate.exists()] + if len(existing) > 1: + raise ReleaseProvenanceError("grader source-tree location is ambiguous") + if existing: + return existing[0] + raise ReleaseProvenanceError("grader source tree or release archive is unavailable") + + +def _validate_source_tree_bindings( + scoring_manifest: dict[str, Any], + provenance: ScoringCohortProvenance, + identity: GraderSourceTreeIdentity, +) -> None: + if identity.manifest_sha256 != provenance.grader_source_tree_sha256: + raise ReleaseProvenanceError( + "reconstructed grader source-tree hash differs from the signed cohort" + ) + artifacts = _mapping(scoring_manifest.get("artifacts"), "scoring manifest artifacts") + for field in ("grader_source_tree_sha256", "grader_source_tree_manifest_sha256"): + if artifacts.get(field) != identity.manifest_sha256: + raise ReleaseProvenanceError(f"scoring manifest {field} does not match reconstruction") + if artifacts.get("grader_source_tree_profile_sha256") != identity.profile_sha256: + raise ReleaseProvenanceError( + "scoring manifest source-tree profile hash does not match reconstruction" + ) + + +def _load_release_chain( + benchmark_dir: Path, + head_bytes: bytes, + head: dict[str, Any], +) -> list[dict[str, Any]]: + chain_path = benchmark_dir / "release-index-chain.json" + if not chain_path.is_file(): + return [head] + _, chain = _load_canonical_json(chain_path, "release index chain") + if set(chain) != {"schema_version", "channel", "indexes"}: + raise ReleaseProvenanceError("release index chain has unsupported fields") + if chain.get("schema_version") != "1.0" or chain.get("channel") != _RELEASE_CHANNEL: + raise ReleaseProvenanceError("release index chain identity is unsupported") + indexes = chain.get("indexes") + if not isinstance(indexes, list) or not indexes: + raise ReleaseProvenanceError("release index chain has no indexes") + if not all(isinstance(candidate, dict) for candidate in indexes): + raise ReleaseProvenanceError("release index chain entries must be objects") + typed_indexes = list(indexes) + if rfc8785.dumps(typed_indexes[-1]) != head_bytes: + raise ReleaseProvenanceError("release index does not match the packaged chain head") + return typed_indexes + + +def _verify_release_chain( + indexes: list[dict[str, Any]], + keyring: dict[str, Any], + *, + now: datetime, + clock_skew: timedelta, +) -> list[_VerifiedReleaseIndex]: + if clock_skew < timedelta(0): + raise ReleaseProvenanceError("release clock skew cannot be negative") + verified: list[_VerifiedReleaseIndex] = [] + previous_issued_at: datetime | None = None + previous_effective_at: datetime | None = None + previous_state_order: int | None = None + state_order = {"active": 0, "frozen": 1, "superseded": 2} + for expected_sequence, index in enumerate(indexes, start=1): + _validate_index_shape(index) + if index.get("channel") != _RELEASE_CHANNEL: + raise ReleaseProvenanceError("release index channel is not acidslide-v1-stable") + if index.get("acceptance_policy") != "highest_valid_chain_head": + raise ReleaseProvenanceError("release index acceptance policy is unsupported") + state = index.get("state") + if not isinstance(state, str) or state not in state_order: + raise ReleaseProvenanceError("release index state is unsupported") + if previous_state_order is not None and state_order[state] < previous_state_order: + raise ReleaseProvenanceError("release index state moves backward") + sequence = index.get("sequence") + if ( + not isinstance(sequence, int) + or isinstance(sequence, bool) + or sequence != expected_sequence + ): + raise ReleaseProvenanceError("release index chain has a sequence gap") + expected_previous = None if not verified else verified[-1].sha256 + if index.get("previous_release_index_sha256") != expected_previous: + raise ReleaseProvenanceError( + "release index previous hash does not match its predecessor" + ) + + issued_at = _timestamp(index.get("issued_at"), "issued_at") + effective_at = _timestamp(index.get("effective_at"), "effective_at") + if effective_at < issued_at: + raise ReleaseProvenanceError("release index effective_at precedes issued_at") + if previous_issued_at is not None and issued_at < previous_issued_at: + raise ReleaseProvenanceError("release index issued_at moves backward") + if previous_effective_at is not None and effective_at < previous_effective_at: + raise ReleaseProvenanceError("release index effective_at moves backward") + if issued_at > now + clock_skew: + raise ReleaseProvenanceError("release index issued_at exceeds the clock-skew bound") + if effective_at > now: + raise ReleaseProvenanceError("release index is not effective yet") + + _validate_index_cohort(index) + _verify_release_signature(index, keyring, issued_at=issued_at, effective_at=effective_at) + verified.append( + _VerifiedReleaseIndex( + document=index, + sha256=_canonical_document_sha256(index), + sequence=expected_sequence, + issued_at=issued_at, + effective_at=effective_at, + ) + ) + previous_issued_at = issued_at + previous_effective_at = effective_at + previous_state_order = state_order[state] + return verified + + +def _validate_index_cohort(index: dict[str, Any]) -> None: + descriptor = _mapping(index.get("cohort_descriptor"), "cohort descriptor") + if descriptor.get("schema_version") != "1.0": + raise ReleaseProvenanceError("unsupported cohort descriptor version") + scoring_manifest_sha256 = _string( + index.get("scoring_manifest_sha256"), "scoring_manifest_sha256" + ) + _require_prefixed_sha256(scoring_manifest_sha256, "scoring_manifest_sha256") + if descriptor.get("scoring_manifest_sha256") != scoring_manifest_sha256: + raise ReleaseProvenanceError("cohort descriptor does not bind the release manifest") + grader_sha256 = _string( + descriptor.get("grader_source_tree_sha256"), "grader_source_tree_sha256" + ) + environment_sha256 = _string( + descriptor.get("environment_attestation_sha256"), + "environment_attestation_sha256", + ) + _require_prefixed_sha256(grader_sha256, "grader_source_tree_sha256") + _require_prefixed_sha256(environment_sha256, "environment_attestation_sha256") + expected = derive_scoring_cohort_id( + scoring_manifest_sha256, + grader_sha256, + environment_sha256, + ) + _require_prefixed_sha256( + _string(index.get("scoring_cohort_id"), "scoring_cohort_id"), "scoring_cohort_id" + ) + if index.get("scoring_cohort_id") != expected: + raise ReleaseProvenanceError("release index scoring_cohort_id is invalid") + + +def _canonical_document_sha256(document: dict[str, Any]) -> str: + return f"sha256:{hashlib.sha256(rfc8785.dumps(document)).hexdigest()}" + + +def _validate_index_shape(index: dict[str, Any]) -> None: + if set(index) != _INDEX_FIELDS: + raise ReleaseProvenanceError("release index has missing or unsupported fields") + if index.get("schema_version") != "1.0": + raise ReleaseProvenanceError("release index schema version is unsupported") + if index.get("release_id") != "acidslide-v1.0.0": + raise ReleaseProvenanceError("release index release_id is unsupported") + if index.get("benchmark_version") != "acidslide-v1.0.0": + raise ReleaseProvenanceError("release index benchmark_version is unsupported") + + +def _release_keys_path(benchmark_dir: Path) -> Path: + """Resolve the repository keyring and the equivalent packaged-wheel location.""" + candidates = (benchmark_dir.parent / "RELEASE_KEYS.json", benchmark_dir / "RELEASE_KEYS.json") + existing = [candidate for candidate in candidates if candidate.is_file()] + if len(existing) > 1: + raise ReleaseProvenanceError("release keyring location is ambiguous") + if existing: + return existing[0] + return candidates[0] + + +def _load_canonical_json(path: Path, label: str) -> tuple[bytes, dict[str, Any]]: + try: + raw = path.read_bytes() + except OSError as exc: + raise ReleaseProvenanceError(f"{label} is unavailable: {path}") from exc + try: + document = json.loads(raw) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise ReleaseProvenanceError(f"{label} is not valid JSON: {path}") from exc + if not isinstance(document, dict): + raise ReleaseProvenanceError(f"{label} must be a JSON object") + try: + canonical = rfc8785.dumps(document) + except rfc8785.CanonicalizationError as exc: + raise ReleaseProvenanceError(f"{label} cannot be canonicalized") from exc + if raw != canonical: + raise ReleaseProvenanceError(f"{label} is not RFC 8785 canonical JSON") + return raw, document + + +def _verification_time(value: datetime | None) -> datetime: + now = value or datetime.now(UTC) + if now.tzinfo is None: + raise ReleaseProvenanceError("release verification time must include a timezone") + return now.astimezone(UTC) + + +def _default_acceptance_state_path() -> Path: + explicit = os.getenv("ACIDSLIDE_RELEASE_STATE_PATH") + if explicit: + return Path(explicit).expanduser() + state_home = os.getenv("XDG_STATE_HOME") + root = Path(state_home).expanduser() if state_home else Path.home() / ".local" / "state" + return root / "acidslide" / "release-head-v1.json" + + +def _accept_release_head( + chain: list[_VerifiedReleaseIndex], + state_path: Path, + *, + trusted_genesis_sha256: str | None, +) -> None: + genesis_sha256 = chain[0].sha256 + head = chain[-1] + if trusted_genesis_sha256 is not None: + _require_prefixed_sha256(trusted_genesis_sha256, "trusted genesis") + if trusted_genesis_sha256 != genesis_sha256: + raise ReleaseProvenanceError( + "release chain does not match the configured trusted genesis" + ) + + with _acceptance_state_lock(state_path): + persisted = _load_acceptance_state(state_path) if state_path.is_file() else None + if persisted is None: + if len(chain) > 1 and trusted_genesis_sha256 is None: + raise ReleaseProvenanceError( + "trusted genesis is required to bootstrap a multi-index release chain" + ) + else: + persisted_genesis = _string( + persisted.get("trusted_genesis_sha256"), "persisted trusted_genesis_sha256" + ) + if persisted_genesis != genesis_sha256: + raise ReleaseProvenanceError("release chain genesis differs from persisted state") + persisted_sequence = persisted.get("sequence") + if not isinstance(persisted_sequence, int) or isinstance(persisted_sequence, bool): + raise ReleaseProvenanceError("persisted release sequence must be an integer") + if persisted_sequence < 1: + raise ReleaseProvenanceError("persisted release sequence must be positive") + persisted_head = _string( + persisted.get("release_index_sha256"), "persisted release_index_sha256" + ) + _require_prefixed_sha256(persisted_head, "persisted release_index_sha256") + if head.sequence < persisted_sequence: + raise ReleaseProvenanceError("release index rollback is prohibited") + if persisted_sequence > len(chain): + raise ReleaseProvenanceError("release chain omits the persisted head") + chain_checkpoint = chain[persisted_sequence - 1].sha256 + if chain_checkpoint != persisted_head: + if head.sequence == persisted_sequence: + raise ReleaseProvenanceError("release index fork at the persisted sequence") + raise ReleaseProvenanceError("release chain forks from the persisted head") + + state = { + "schema_version": "1.0", + "channel": _RELEASE_CHANNEL, + "trusted_genesis_sha256": genesis_sha256, + "sequence": head.sequence, + "release_index_sha256": head.sha256, + } + if persisted != state: + _write_acceptance_state(state_path, state) + + +def _load_acceptance_state(path: Path) -> dict[str, Any]: + _, state = _load_canonical_json(path, "persisted release acceptance state") + if set(state) != { + "schema_version", + "channel", + "trusted_genesis_sha256", + "sequence", + "release_index_sha256", + }: + raise ReleaseProvenanceError("persisted release acceptance state has unsupported fields") + if state.get("schema_version") != "1.0" or state.get("channel") != _RELEASE_CHANNEL: + raise ReleaseProvenanceError("persisted release acceptance state identity is unsupported") + return state + + +@contextmanager +def _acceptance_state_lock(state_path: Path) -> Iterator[None]: + try: + state_path.parent.mkdir(parents=True, exist_ok=True) + lock_path = state_path.with_name(f"{state_path.name}.lock") + descriptor = os.open(lock_path, os.O_RDWR | os.O_CREAT, 0o600) + with os.fdopen(descriptor, "a+b") as lock_file: + fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX) + yield + fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN) + except OSError as exc: + raise ReleaseProvenanceError( + f"release acceptance state is unavailable: {state_path}" + ) from exc + + +def _write_acceptance_state(path: Path, state: dict[str, Any]) -> None: + descriptor: int | None = None + temporary_name: str | None = None + try: + descriptor, temporary_name = tempfile.mkstemp( + prefix=f".{path.name}.", suffix=".tmp", dir=path.parent + ) + os.fchmod(descriptor, 0o600) + with os.fdopen(descriptor, "wb") as stream: + descriptor = None + stream.write(rfc8785.dumps(state)) + stream.flush() + os.fsync(stream.fileno()) + os.replace(temporary_name, path) + temporary_name = None + directory_descriptor = os.open(path.parent, os.O_RDONLY) + try: + os.fsync(directory_descriptor) + finally: + os.close(directory_descriptor) + except OSError as exc: + raise ReleaseProvenanceError(f"could not persist release acceptance state: {path}") from exc + finally: + if descriptor is not None: + os.close(descriptor) + if temporary_name is not None: + with suppress(FileNotFoundError): + os.unlink(temporary_name) + + +def _require_prefixed_sha256(value: str, name: str) -> None: + if not _PREFIXED_SHA256.fullmatch(value): + raise ReleaseProvenanceError(f"{name} is not a canonical prefixed SHA-256") + + +def _verify_release_signature( + index: dict[str, Any], + keyring: dict[str, Any], + *, + issued_at: datetime, + effective_at: datetime, +) -> None: + _validate_keyring_shape(keyring) + signatures = index.get("signatures") + keys = keyring.get("keys") + if not isinstance(signatures, list) or not signatures: + raise ReleaseProvenanceError("release index has no signatures") + if not isinstance(keys, list) or not keys: + raise ReleaseProvenanceError("release keyring has no keys") + + signed_payload = dict(index) + signed_payload.pop("signatures", None) + message = rfc8785.dumps(signed_payload) + keys_by_id: dict[str, dict[str, Any]] = {} + for key in keys: + if not isinstance(key, dict): + raise ReleaseProvenanceError("release keyring entries must be objects") + key_id = key.get("key_id") + if not isinstance(key_id, str): + raise ReleaseProvenanceError("release key_id must be a string") + if key_id in keys_by_id: + raise ReleaseProvenanceError(f"release keyring contains duplicate key_id: {key_id}") + keys_by_id[key_id] = key + for signature in signatures: + if not isinstance(signature, dict) or set(signature) != _SIGNATURE_FIELDS: + raise ReleaseProvenanceError("release signature has missing or unsupported fields") + if signature.get("algorithm") != "Ed25519": + raise ReleaseProvenanceError("release signature algorithm is unsupported") + signature_key_id = signature.get("key_id") + if not isinstance(signature_key_id, str) or not _KEY_ID.fullmatch(signature_key_id): + raise ReleaseProvenanceError("release signature key_id is invalid") + key = keys_by_id.get(signature_key_id) + if not isinstance(key, dict) or not _key_valid_for_release(key, issued_at, effective_at): + continue + try: + public_bytes = base64.b64decode( + _string(key.get("public_key_base64"), "public key"), validate=True + ) + signature_bytes = base64.b64decode( + _string(signature.get("signature_base64"), "release signature"), validate=True + ) + Ed25519PublicKey.from_public_bytes(public_bytes).verify(signature_bytes, message) + except (ValueError, InvalidSignature): + continue + return + raise ReleaseProvenanceError( + "release index has no valid signature from a non-revoked key valid at released_at" + ) + + +def _validate_keyring_shape(keyring: dict[str, Any]) -> None: + if set(keyring) != {"schema_version", "keys"} or keyring.get("schema_version") != "1.0": + raise ReleaseProvenanceError("release keyring identity or fields are unsupported") + keys = keyring.get("keys") + if not isinstance(keys, list) or not keys: + raise ReleaseProvenanceError("release keyring has no keys") + for key in keys: + if not isinstance(key, dict) or set(key) != _KEY_FIELDS: + raise ReleaseProvenanceError("release key has missing or unsupported fields") + key_id = key.get("key_id") + if not isinstance(key_id, str) or not _KEY_ID.fullmatch(key_id): + raise ReleaseProvenanceError("release key_id is invalid") + if key.get("algorithm") != "Ed25519": + raise ReleaseProvenanceError("release key algorithm is unsupported") + try: + public_bytes = base64.b64decode( + _string(key.get("public_key_base64"), "public key"), validate=True + ) + except ValueError as exc: + raise ReleaseProvenanceError("release public key is not canonical base64") from exc + if len(public_bytes) != 32: + raise ReleaseProvenanceError("release public key is not 32 bytes") + _timestamp(key.get("valid_from"), "valid_from") + for name in ("valid_until", "revoked_at"): + value = key.get(name) + if value is not None: + _timestamp(value, name) + + +def _key_valid_for_release( + key: dict[str, Any], issued_at: datetime, effective_at: datetime +) -> bool: + if key.get("algorithm") != "Ed25519": + return False + try: + valid_from = _timestamp(key.get("valid_from"), "valid_from") + valid_until_raw = key.get("valid_until") + valid_until = ( + _timestamp(valid_until_raw, "valid_until") if valid_until_raw is not None else None + ) + revoked_at_raw = key.get("revoked_at") + revoked_at = ( + _timestamp(revoked_at_raw, "revoked_at") if revoked_at_raw is not None else None + ) + except ReleaseProvenanceError: + return False + if issued_at < valid_from or effective_at < valid_from: + return False + if valid_until is not None and (issued_at > valid_until or effective_at > valid_until): + return False + return revoked_at is None or (issued_at < revoked_at and effective_at < revoked_at) + + +def _timestamp(value: object, name: str) -> datetime: + if not isinstance(value, str): + raise ReleaseProvenanceError(f"{name} must be an RFC 3339 timestamp") + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError as exc: + raise ReleaseProvenanceError(f"{name} must be an RFC 3339 timestamp") from exc + if parsed.tzinfo is None: + raise ReleaseProvenanceError(f"{name} must include a timezone") + return parsed + + +def _mapping(value: object, name: str) -> dict[str, Any]: + if not isinstance(value, dict): + raise ReleaseProvenanceError(f"{name} must be an object") + return value + + +def _string(value: object, name: str) -> str: + if not isinstance(value, str): + raise ReleaseProvenanceError(f"{name} must be a string") + return value diff --git a/acidslide-v1/grader/acidslide/release_evidence.py b/acidslide-v1/grader/acidslide/release_evidence.py new file mode 100644 index 0000000..41bdf2a --- /dev/null +++ b/acidslide-v1/grader/acidslide/release_evidence.py @@ -0,0 +1,280 @@ +"""Fail-closed validation for review and release-evidence projections.""" + +from __future__ import annotations + +import hashlib +import math +from typing import TYPE_CHECKING, Any, Protocol + +import rfc8785 + +if TYPE_CHECKING: + from collections.abc import Mapping + +EXPORT_RUN_COUNT = 100 +EXPORT_PAGE_COUNT = 20 +EXPORT_RUN_PAIR_COUNT = 4_950 +EXPORT_PAGE_PAIR_COMPARISON_COUNT = 99_000 +EXPORT_REQUIRED_MINIMUM_SSIM = 0.99999 + + +class ValidationResult(Protocol): + """Minimal result collector used by normative and release validation.""" + + errors: list[str] + notes: list[str] + + def require(self, condition: bool, message: str) -> None: ... + + +def prompt_oracle_review_sha256(oracle: dict[str, Any]) -> str: + """Hash the domain-separated, approval-free prompt-oracle projection.""" + projection: dict[str, Any] = { + "domain": "AcidSlide prompt requirements oracle review v1", + "oracle": {key: value for key, value in oracle.items() if key != "independent_reviews"}, + } + return hashlib.sha256(rfc8785.dumps(projection)).hexdigest() + + +def assertion_inventory_review_sha256(inventory: dict[str, Any]) -> str: + """Hash the domain-separated, approval-free assertion-inventory projection.""" + projection: dict[str, Any] = { + "domain": "AcidSlide scored assertion inventory review v1", + "inventory": {key: value for key, value in inventory.items() if key != "review"}, + } + return f"sha256:{hashlib.sha256(rfc8785.dumps(projection)).hexdigest()}" + + +def validate_prompt_review_approvals( + result: ValidationResult, + oracle: dict[str, Any], +) -> None: + """Require two distinct approvals over the exact prompt-oracle projection.""" + approvals_value = oracle.get("independent_reviews", []) + approvals = approvals_value if isinstance(approvals_value, list) else [] + valid_approvals = [approval for approval in approvals if isinstance(approval, dict)] + reviewer_ids = [ + approval.get("reviewer_id") + for approval in valid_approvals + if isinstance(approval.get("reviewer_id"), str) + ] + expected_sha256 = prompt_oracle_review_sha256(oracle) + result.require( + len(valid_approvals) >= 2 + and len(valid_approvals) == len(approvals) + and len(reviewer_ids) == len(valid_approvals) + and len(reviewer_ids) == len(set(reviewer_ids)), + "release mode: prompt requirements oracle lacks two distinct reviewer approvals", + ) + result.require( + bool(valid_approvals) + and all( + approval.get("decision") == "approved" + and approval.get("reviewed_oracle_sha256") == expected_sha256 + for approval in valid_approvals + ), + "release mode: prompt reviewer approval hash does not match the review projection", + ) + + +def validate_assertion_inventory_approvals( + result: ValidationResult, + inventory: dict[str, Any], +) -> None: + """Require two distinct approvals over the exact assertion projection.""" + review = inventory.get("review", {}) + approvals_value = review.get("reviewer_approvals", []) if isinstance(review, dict) else [] + approvals = approvals_value if isinstance(approvals_value, list) else [] + valid_approvals = [approval for approval in approvals if isinstance(approval, dict)] + reviewer_ids = [ + approval.get("reviewer_id") + for approval in valid_approvals + if isinstance(approval.get("reviewer_id"), str) + ] + expected_sha256 = assertion_inventory_review_sha256(inventory) + result.require( + isinstance(review, dict) + and review.get("status") == "approved" + and len(valid_approvals) >= 2 + and len(valid_approvals) == len(approvals) + and len(reviewer_ids) == len(valid_approvals) + and len(reviewer_ids) == len(set(reviewer_ids)), + "release mode: scored assertion inventory lacks two distinct reviewer approvals", + ) + result.require( + bool(valid_approvals) + and all( + approval.get("inventory_sha256") == expected_sha256 for approval in valid_approvals + ), + "release mode: assertion reviewer approval hash does not match the review projection", + ) + + +def _objects(value: object) -> list[dict[str, Any]]: + if not isinstance(value, list): + return [] + return [item for item in value if isinstance(item, dict)] + + +def _score(value: object) -> float | None: + if isinstance(value, bool) or not isinstance(value, (int, float)): + return None + score = float(value) + return score if math.isfinite(score) and 0.0 <= score <= 1.0 else None + + +def validate_export_determinism_evidence( + result: ValidationResult, + evidence: dict[str, Any], + *, + expected_bindings: Mapping[str, Any] | None = None, +) -> None: + """Recompute the complete 100-run export-determinism evidence matrix.""" + if not evidence: + return + + threshold = _score(evidence.get("required_minimum_ssim")) + result.require( + threshold == EXPORT_REQUIRED_MINIMUM_SSIM, + "export determinism evidence has the wrong required minimum SSIM", + ) + result.require( + evidence.get("run_count") == EXPORT_RUN_COUNT + and evidence.get("page_count") == EXPORT_PAGE_COUNT + and evidence.get("run_pair_count") == EXPORT_RUN_PAIR_COUNT + and evidence.get("page_pair_comparison_count") == EXPORT_PAGE_PAIR_COMPARISON_COUNT, + "export determinism evidence declares the wrong run/comparison counts", + ) + + bindings = evidence.get("bindings") + if expected_bindings is not None: + result.require( + isinstance(bindings, dict) and bindings == dict(expected_bindings), + "export determinism evidence is bound to the wrong environment or gold identity", + ) + + expected_pages = list(range(1, EXPORT_PAGE_COUNT + 1)) + runs = _objects(evidence.get("runs")) + result.require( + len(runs) == EXPORT_RUN_COUNT + and [run.get("run") for run in runs] == list(range(1, EXPORT_RUN_COUNT + 1)), + "export determinism evidence runs must be ordered exactly 1..100", + ) + for run in runs: + pages = _objects(run.get("pages")) + result.require( + len(pages) == EXPORT_PAGE_COUNT + and [page.get("page") for page in pages] == expected_pages, + f"export determinism run {run.get('run')} pages must be ordered exactly 1..20", + ) + + canonical_run_number = evidence.get("canonical_run") + result.require( + canonical_run_number == 1, + "export determinism evidence canonical_run must be run 1", + ) + if runs and isinstance(bindings, dict): + canonical_run = runs[0] + canonical_pages = _objects(canonical_run.get("pages")) + result.require( + canonical_run.get("pdf_sha256") == bindings.get("canonical_pdf_sha256") + and [page.get("png_sha256") for page in canonical_pages] + == bindings.get("canonical_png_sha256s"), + "export determinism canonical run does not match the bound gold export hashes", + ) + + expected_pairs = [ + (run_a, run_b) + for run_a in range(1, EXPORT_RUN_COUNT + 1) + for run_b in range(run_a + 1, EXPORT_RUN_COUNT + 1) + ] + run_pairs = _objects(evidence.get("run_pairs")) + actual_pairs = [(pair.get("run_a"), pair.get("run_b")) for pair in run_pairs] + result.require( + len(run_pairs) == EXPORT_RUN_PAIR_COUNT and actual_pairs == expected_pairs, + "export determinism run pairs must be the ordered complete 100-choose-2 matrix", + ) + + comparison_count = 0 + all_scores: list[float] = [] + scores_by_page: dict[int, list[float]] = {page: [] for page in range(1, EXPORT_PAGE_COUNT + 1)} + pair_minima_match = True + pair_pages_match = True + for pair in run_pairs: + comparisons = _objects(pair.get("page_comparisons")) + comparison_count += len(comparisons) + if ( + len(comparisons) != EXPORT_PAGE_COUNT + or [comparison.get("page") for comparison in comparisons] != expected_pages + ): + pair_pages_match = False + pair_scores: list[float] = [] + for comparison in comparisons: + page = comparison.get("page") + score = _score(comparison.get("ssim")) + if score is None: + continue + pair_scores.append(score) + all_scores.append(score) + if isinstance(page, int) and page in scores_by_page: + scores_by_page[page].append(score) + recorded_minimum = _score(pair.get("minimum_ssim")) + if ( + len(pair_scores) != EXPORT_PAGE_COUNT + or recorded_minimum is None + or recorded_minimum != min(pair_scores) + ): + pair_minima_match = False + + result.require( + pair_pages_match, + "each export determinism run pair must compare pages exactly 1..20", + ) + result.require( + comparison_count == EXPORT_PAGE_PAIR_COMPARISON_COUNT + and len(all_scores) == EXPORT_PAGE_PAIR_COMPARISON_COUNT, + "export determinism evidence must contain exactly 99,000 numeric page comparisons", + ) + result.require( + pair_minima_match, + "export determinism run-pair minimum SSIM values do not recompute", + ) + + recorded_page_minima = _objects(evidence.get("minimum_ssim_by_page")) + page_minima_match = ( + len(recorded_page_minima) == EXPORT_PAGE_COUNT + and [item.get("page") for item in recorded_page_minima] == expected_pages + ) + computed_page_minima: list[float] = [] + for page, item in zip(expected_pages, recorded_page_minima, strict=False): + scores = scores_by_page[page] + recorded = _score(item.get("minimum_ssim")) + if len(scores) != EXPORT_RUN_PAIR_COUNT: + page_minima_match = False + continue + computed = min(scores) + computed_page_minima.append(computed) + if recorded != computed: + page_minima_match = False + result.require( + page_minima_match and len(computed_page_minima) == EXPORT_PAGE_COUNT, + "export determinism per-page minimum SSIM values do not recompute", + ) + + recorded_global_minimum = _score(evidence.get("global_minimum_ssim")) + computed_global_minimum = min(all_scores) if all_scores else None + result.require( + recorded_global_minimum is not None + and recorded_global_minimum == computed_global_minimum + and bool(computed_page_minima) + and recorded_global_minimum == min(computed_page_minima), + "export determinism global minimum SSIM does not recompute", + ) + result.require( + threshold is not None + and bool(computed_page_minima) + and all(minimum >= threshold for minimum in computed_page_minima) + and computed_global_minimum is not None + and computed_global_minimum >= threshold, + "export determinism per-page or global minimum SSIM is below 0.99999", + ) diff --git a/acidslide-v1/grader/acidslide/resources.py b/acidslide-v1/grader/acidslide/resources.py new file mode 100644 index 0000000..8dd563e --- /dev/null +++ b/acidslide-v1/grader/acidslide/resources.py @@ -0,0 +1,111 @@ +"""Locate benchmark and schema data in source, Docker, and installed packages.""" + +from __future__ import annotations + +import os +from pathlib import Path + + +class BenchmarkDataError(RuntimeError): + """Raised when the grader cannot locate a usable benchmark package.""" + + +def resolve_benchmark_dir(explicit: Path | None = None) -> Path: + """Return the benchmark data directory, or raise with actionable context.""" + candidates = _candidates( + explicit=explicit, + environment_variable="ACIDSLIDE_BENCHMARK_DIR", + packaged_name="benchmark", + source_name="benchmark", + ) + for candidate in candidates: + if _is_benchmark_dir(candidate): + return candidate.resolve() + + searched = ", ".join(str(path) for path in candidates) + msg = ( + "AcidSlide benchmark data is unavailable. Expected checklist/ and tiers/ " + f"under one of: {searched}" + ) + raise BenchmarkDataError(msg) + + +def resolve_schema_dir(explicit: Path | None = None) -> Path: + """Return the ECMA-376 Transitional XSD directory.""" + candidates = _candidates( + explicit=explicit, + environment_variable="ACIDSLIDE_SCHEMA_DIR", + packaged_name="schemas/ecma-376/xsd-transitional", + source_name="schemas/ecma-376/xsd-transitional", + ) + for candidate in candidates: + if candidate.is_dir() and (candidate / "pml.xsd").is_file(): + return candidate.resolve() + + searched = ", ".join(str(path) for path in candidates) + msg = f"ECMA-376 XSD schemas are unavailable; searched: {searched}" + raise FileNotFoundError(msg) + + +def resolve_normative_schema_file(name: str, explicit: Path | None = None) -> Path: + """Return one content-addressed normative schema/profile file. + + ``name`` is deliberately restricted to a basename so callers cannot turn + package-data lookup into arbitrary path traversal. + """ + if Path(name).name != name: + raise ValueError(f"Normative schema name must be a basename: {name!r}") + candidates = _candidates( + explicit=explicit, + environment_variable="ACIDSLIDE_SCHEMA_PROFILE_DIR", + packaged_name="schemas", + source_name="schemas", + ) + for candidate in candidates: + path = candidate if explicit is not None and candidate.is_file() else candidate / name + if path.is_file(): + return path.resolve() + + searched = ", ".join(str(path) for path in candidates) + raise FileNotFoundError( + f"Normative schema/profile {name!r} is unavailable; searched: {searched}" + ) + + +def _candidates( + *, + explicit: Path | None, + environment_variable: str, + packaged_name: str, + source_name: str, +) -> list[Path]: + if explicit is not None: + return [explicit.expanduser()] + + configured = os.environ.get(environment_variable) + if configured: + return [Path(configured).expanduser()] + + package_dir = Path(__file__).resolve().parent + return _deduplicate( + [ + package_dir / "data" / packaged_name, + package_dir.parents[1] / source_name, + Path("/opt/acidslide") / source_name, + ] + ) + + +def _is_benchmark_dir(path: Path) -> bool: + return path.is_dir() and (path / "checklist").is_dir() and (path / "tiers").is_dir() + + +def _deduplicate(paths: list[Path]) -> list[Path]: + unique: list[Path] = [] + seen: set[str] = set() + for path in paths: + key = str(path.absolute()) + if key not in seen: + seen.add(key) + unique.append(path) + return unique diff --git a/acidslide-v1/grader/acidslide/scene_graph.py b/acidslide-v1/grader/acidslide/scene_graph.py new file mode 100644 index 0000000..b39c791 --- /dev/null +++ b/acidslide-v1/grader/acidslide/scene_graph.py @@ -0,0 +1,877 @@ +"""Normative, deterministic scene-graph extraction from MCE-resolved PPTX packages.""" + +from __future__ import annotations + +import hashlib +import json +import posixpath +import unicodedata +import zipfile +from dataclasses import dataclass +from decimal import Decimal +from pathlib import Path, PurePosixPath +from typing import Any +from urllib.parse import unquote, urlsplit + +import rfc8785 +from lxml import etree + +from acidslide.mce import MC_NAMESPACE +from acidslide.package_hash import sha256_file +from acidslide.resources import resolve_normative_schema_file + +PRESENTATION = "ppt/presentation.xml" +PRESENTATION_RELS = "ppt/_rels/presentation.xml.rels" +REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships" +P_NS = "http://schemas.openxmlformats.org/presentationml/2006/main" +A_NS = "http://schemas.openxmlformats.org/drawingml/2006/main" +R_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" +C_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart" + + +class SceneGraphError(ValueError): + """The package cannot be represented under the frozen scene-graph profile.""" + + +@dataclass(frozen=True) +class Relationship: + relationship_id: str + relationship_type: str + target: str + + def as_dict(self) -> dict[str, str]: + return { + "id": self.relationship_id, + "type": self.relationship_type, + "target_mode": "Internal", + "target": f"/{self.target}", + } + + +def canonical_scene_graph_bytes(scene_graph: dict[str, Any]) -> bytes: + """Return the one fixture serialization frozen by the normative profile.""" + return rfc8785.dumps(scene_graph) + + +def extract_normative_scene_graph( + resolved_package: Path, + *, + profile_path: Path | None = None, + selected_slides: set[int] | None = None, +) -> dict[str, Any]: + """Extract one schema-shaped graph from an already MCE-resolved package. + + The function deliberately does not run MCE preprocessing. Any remaining MCE + element or attribute proves that the caller supplied the wrong package state + and is rejected before structural evidence is emitted. + """ + resolved_profile, profile = _load_profile(profile_path) + parts = _read_parts(resolved_package) + _assert_mce_resolved(parts) + relationships = _relationship_graph(parts) + presentation = _parse_xml(_required_part(parts, PRESENTATION), PRESENTATION) + if presentation.tag != f"{{{P_NS}}}presentation": + raise SceneGraphError(f"Unexpected presentation root: {presentation.tag!r}") + slide_parts = _ordered_slide_parts(presentation, relationships) + allowed_counts = profile["input_contract"]["allowed_slide_counts"] + if len(slide_parts) not in allowed_counts: + raise SceneGraphError( + f"Scene-graph profile permits slide counts {allowed_counts}; found {len(slide_parts)}" + ) + selected = set(range(1, len(slide_parts) + 1)) if selected_slides is None else selected_slides + if not selected or any(number < 1 or number > len(slide_parts) for number in selected): + raise SceneGraphError("Selected slide numbers are outside the resolved presentation") + slide_size = _slide_size(presentation) + slides = [ + _extract_slide(number, part, parts, relationships) + for number, part in enumerate(slide_parts, 1) + if number in selected + ] + return { + "schema_version": "1.0", + "profile_sha256": f"sha256:{sha256_file(resolved_profile)}", + "mce_resolved_package_sha256": f"sha256:{sha256_file(resolved_package)}", + "units": "EMU", + "slide_size": slide_size, + "slides": slides, + "gold_ooxml_is_oracle": False, + } + + +def per_slide_scene_graphs(deck_graph: dict[str, Any]) -> dict[int, dict[str, Any]]: + """Split a deck graph into independently schema-valid per-slide documents.""" + slides = deck_graph.get("slides") + if not isinstance(slides, list): + raise SceneGraphError("Scene graph has no slide array") + result: dict[int, dict[str, Any]] = {} + for slide in slides: + if not isinstance(slide, dict) or not isinstance(slide.get("slide"), int): + raise SceneGraphError("Scene graph contains a malformed slide record") + number = int(slide["slide"]) + if number in result: + raise SceneGraphError(f"Scene graph contains duplicate slide {number}") + result[number] = dict(deck_graph) | {"slides": [slide]} + return result + + +def _load_profile(explicit: Path | None) -> tuple[Path, dict[str, Any]]: + path = resolve_normative_schema_file("scene-graph-profile-v1.json", explicit) + try: + profile: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as exc: + raise SceneGraphError(f"Scene-graph profile is unreadable: {path}") from exc + if profile.get("profile_id") != "acidslide-scene-graph-profile-v1": + raise SceneGraphError(f"Unsupported scene-graph profile: {path}") + return path, profile + + +def _read_parts(package_path: Path) -> dict[str, bytes]: + parts: dict[str, bytes] = {} + try: + with zipfile.ZipFile(package_path) as package: + for info in package.infolist(): + if info.is_dir(): + continue + name = info.filename + _validate_part_name(name) + if name in parts: + raise SceneGraphError(f"Duplicate ZIP part name: {name}") + if info.flag_bits & 0x1: + raise SceneGraphError(f"Encrypted ZIP part is prohibited: {name}") + parts[name] = package.read(info) + except (OSError, zipfile.BadZipFile) as exc: + raise SceneGraphError("Resolved package is not a readable ZIP archive") from exc + if not parts: + raise SceneGraphError("Resolved package contains no parts") + return parts + + +def _validate_part_name(name: str) -> None: + if not name or name.startswith("/") or "\\" in name or "\x00" in name: + raise SceneGraphError(f"Unsafe OPC part name: {name!r}") + if unicodedata.normalize("NFC", name) != name: + raise SceneGraphError(f"Non-NFC OPC part name: {name!r}") + if any(part in {"", ".", ".."} for part in PurePosixPath(name).parts): + raise SceneGraphError(f"Unsafe OPC part name: {name!r}") + + +def _required_part(parts: dict[str, bytes], name: str) -> bytes: + try: + return parts[name] + except KeyError as exc: + raise SceneGraphError(f"Required OPC part is missing: /{name}") from exc + + +def _parse_xml(content: bytes, part_name: str) -> etree._Element: + parser = etree.XMLParser( + resolve_entities=False, + no_network=True, + dtd_validation=False, + load_dtd=False, + huge_tree=False, + remove_blank_text=False, + ) + try: + return etree.fromstring(content, parser=parser) + except etree.XMLSyntaxError as exc: + raise SceneGraphError(f"Malformed XML part: /{part_name}") from exc + + +def _assert_mce_resolved(parts: dict[str, bytes]) -> None: + for name in sorted(parts): + if not name.startswith("ppt/") or not name.endswith(".xml"): + continue + root = _parse_xml(parts[name], name) + for element in root.iter(): + if _namespace(str(element.tag)) == MC_NAMESPACE: + raise SceneGraphError(f"Unresolved MCE element remains in /{name}: {element.tag}") + for attribute in element.attrib: + if _namespace(str(attribute)) == MC_NAMESPACE: + raise SceneGraphError( + f"Unresolved MCE attribute remains in /{name}: {attribute!r}" + ) + + +def _relationship_graph(parts: dict[str, bytes]) -> dict[str, list[Relationship]]: + graph: dict[str, list[Relationship]] = {} + for rels_name in sorted(name for name in parts if name.endswith(".rels")): + source = _source_for_relationship_part(rels_name) + if source in graph: + raise SceneGraphError(f"More than one relationship part exists for /{source}") + root = _parse_xml(parts[rels_name], rels_name) + if root.tag != f"{{{REL_NS}}}Relationships": + raise SceneGraphError(f"Unexpected relationship root in /{rels_name}") + records: list[Relationship] = [] + identifiers: set[str] = set() + for child in root: + if child.tag != f"{{{REL_NS}}}Relationship": + raise SceneGraphError(f"Unexpected relationship element in /{rels_name}") + relationship_id = child.get("Id", "") + relationship_type = child.get("Type", "") + target = child.get("Target", "") + if not relationship_id or relationship_id in identifiers: + raise SceneGraphError(f"Duplicate or missing relationship ID in /{rels_name}") + if not relationship_type or not urlsplit(relationship_type).scheme: + raise SceneGraphError(f"Malformed relationship type in /{rels_name}") + if child.get("TargetMode", "Internal") != "Internal": + raise SceneGraphError(f"External relationship is prohibited in /{rels_name}") + resolved_target = _resolve_relationship_target(source, target) + if resolved_target not in parts: + raise SceneGraphError( + f"Dangling relationship target: /{rels_name} -> /{resolved_target}" + ) + identifiers.add(relationship_id) + records.append(Relationship(relationship_id, relationship_type, resolved_target)) + graph[source] = sorted(records, key=lambda item: item.relationship_id) + _required_part(parts, PRESENTATION_RELS) + return graph + + +def _source_for_relationship_part(name: str) -> str: + if name == "_rels/.rels": + return "" + directory, filename = posixpath.split(name) + if posixpath.basename(directory) != "_rels" or not filename.endswith(".rels"): + raise SceneGraphError(f"Malformed relationship part name: /{name}") + source_directory = posixpath.dirname(directory) + source_name = filename[: -len(".rels")] + source = posixpath.join(source_directory, source_name) + _validate_part_name(source) + return source + + +def _resolve_relationship_target(source: str, target: str) -> str: + parsed = urlsplit(target) + if parsed.scheme or parsed.netloc or parsed.query or parsed.fragment or not parsed.path: + raise SceneGraphError(f"Unsupported OPC relationship target URI: {target!r}") + try: + decoded = unquote(parsed.path, errors="strict") + except UnicodeDecodeError as exc: + raise SceneGraphError( + f"Invalid percent encoding in relationship target: {target!r}" + ) from exc + candidate = ( + posixpath.normpath(decoded.lstrip("/")) + if decoded.startswith("/") + else posixpath.normpath(posixpath.join(posixpath.dirname(source), decoded)) + ) + _validate_part_name(candidate) + return candidate + + +def _ordered_slide_parts( + presentation: etree._Element, + relationship_graph: dict[str, list[Relationship]], +) -> list[str]: + by_id = {item.relationship_id: item for item in relationship_graph.get(PRESENTATION, [])} + slide_parts: list[str] = [] + seen: set[str] = set() + for slide_id in presentation.iter(f"{{{P_NS}}}sldId"): + relationship_id = slide_id.get(f"{{{R_NS}}}id", "") + relationship = by_id.get(relationship_id) + if relationship is None or not relationship.relationship_type.endswith("/slide"): + raise SceneGraphError( + f"Presentation slide ID has no slide relationship: {relationship_id!r}" + ) + if relationship.target in seen: + raise SceneGraphError( + f"Presentation references a slide part twice: /{relationship.target}" + ) + seen.add(relationship.target) + slide_parts.append(relationship.target) + if not slide_parts: + raise SceneGraphError("Presentation contains no ordered slide IDs") + return slide_parts + + +def _slide_size(presentation: etree._Element) -> dict[str, int]: + size = presentation.find(f"{{{P_NS}}}sldSz") + if size is None: + raise SceneGraphError("Presentation has no p:sldSz") + width = _required_integer(size, "cx", minimum=1) + height = _required_integer(size, "cy", minimum=1) + return {"width": width, "height": height} + + +def _extract_slide( + slide_number: int, + part_name: str, + parts: dict[str, bytes], + relationship_graph: dict[str, list[Relationship]], +) -> dict[str, Any]: + slide = _parse_xml(_required_part(parts, part_name), part_name) + if slide.tag != f"{{{P_NS}}}sld": + raise SceneGraphError(f"Unexpected slide root in /{part_name}: {slide.tag!r}") + slide_relationships = relationship_graph.get(part_name, []) + layout = _one_relationship(slide_relationships, "/slideLayout", part_name) + layout_relationships = relationship_graph.get(layout.target, []) + master = _one_relationship(layout_relationships, "/slideMaster", layout.target) + common = slide.find(f"{{{P_NS}}}cSld") + shape_tree = common.find(f"{{{P_NS}}}spTree") if common is not None else None + if shape_tree is None: + raise SceneGraphError(f"Slide has no p:cSld/p:spTree: /{part_name}") + relationship_by_id = {item.relationship_id: item for item in slide_relationships} + nodes = _extract_nodes( + shape_tree, + slide_number, + part_name, + relationship_by_id, + parts, + parent_ids=(), + structural_prefix=(), + locator_prefix="/p:sld/p:cSld/p:spTree", + ) + return { + "slide": slide_number, + "part_name": f"/{part_name}", + "layout_part": f"/{layout.target}", + "master_part": f"/{master.target}", + "nodes": nodes, + "relationships": [item.as_dict() for item in slide_relationships], + } + + +def _one_relationship(relationships: list[Relationship], suffix: str, source: str) -> Relationship: + matches = [item for item in relationships if item.relationship_type.endswith(suffix)] + if len(matches) != 1: + raise SceneGraphError( + f"/{source} must have exactly one {suffix.removeprefix('/')} relationship" + ) + return matches[0] + + +def _extract_nodes( + shape_tree: etree._Element, + slide_number: int, + source_part: str, + relationships: dict[str, Relationship], + parts: dict[str, bytes], + *, + parent_ids: tuple[str, ...], + structural_prefix: tuple[int, ...], + locator_prefix: str, +) -> list[dict[str, Any]]: + nodes: list[dict[str, Any]] = [] + occurrences: dict[str, int] = {} + supported = {"sp", "pic", "graphicFrame", "grpSp", "cxnSp"} + for child in shape_tree: + local_name = etree.QName(child).localname + if local_name not in supported: + continue + occurrences[local_name] = occurrences.get(local_name, 0) + 1 + structural_path = structural_prefix + (len(nodes),) + node_id = f"s{slide_number}:n" + ".".join(str(value) for value in structural_path) + locator = f"{locator_prefix}/p:{local_name}[{occurrences[local_name]}]" + nodes.append( + _extract_node( + child, + node_id, + len(nodes), + slide_number, + source_part, + locator, + relationships, + parts, + parent_ids=parent_ids, + structural_path=structural_path, + ) + ) + return nodes + + +def _extract_node( + element: etree._Element, + node_id: str, + z_index: int, + slide_number: int, + source_part: str, + locator: str, + relationships: dict[str, Relationship], + parts: dict[str, bytes], + *, + parent_ids: tuple[str, ...], + structural_path: tuple[int, ...], +) -> dict[str, Any]: + source_xml_kind = etree.QName(element).localname + text_runs = _text_runs(element) + placeholder_type, placeholder_index = _placeholder(element) + field_types = sorted( + {field.get("type", "") for field in element.iter(f"{{{A_NS}}}fld") if field.get("type")} + ) + table_dimensions = _table_dimensions(element) + chart_type, chart_summary = _chart_properties(element, relationships, parts) + asset_sha256 = _asset_hash(element, relationships, parts) + kind = _node_kind( + source_xml_kind, + element, + text_runs, + placeholder_type, + field_types, + table_dimensions, + chart_type, + ) + property_container = _property_container(element) + fill = _fill(property_container) + children: list[dict[str, Any]] = [] + if source_xml_kind == "grpSp": + children = _extract_nodes( + element, + slide_number, + source_part, + relationships, + parts, + parent_ids=parent_ids + (node_id,), + structural_prefix=structural_path, + locator_prefix=locator, + ) + native_properties: dict[str, Any] = { + "source_xml_kind": source_xml_kind, + "subtype": _subtype( + kind, + element, + placeholder_type, + chart_type, + ), + "parent_group_path": list(parent_ids), + "name": _nonvisual_name(element), + "placeholder_type": placeholder_type, + "placeholder_index": placeholder_index, + "table_dimensions": table_dimensions, + "chart_type": chart_type, + "chart_data_summary": chart_summary, + "field_type": field_types[0] if len(field_types) == 1 else None, + "field_types": field_types, + "paragraph_properties": _paragraph_properties(element), + "fill": fill, + "stroke": _stroke(property_container), + "opacity": _opacity(fill), + "shadow": _has_shadow(property_container), + "crop": _crop(element), + "crop_to_shape": _crop_to_shape(element), + "hyperlink_targets": _hyperlinks(element, relationships), + } + return { + "node_id": node_id, + "kind": kind, + "source_part": f"/{source_part}", + "source_locator": locator, + "z_index": z_index, + "bbox": _bbox(element), + "rotation_degrees": _rotation(element), + "hidden": _hidden(element), + "text_runs": text_runs, + "asset_sha256": asset_sha256, + "native_properties": native_properties, + "children": children, + } + + +def _node_kind( + source_xml_kind: str, + element: etree._Element, + text_runs: list[dict[str, Any]], + placeholder_type: str | None, + field_types: list[str], + table_dimensions: dict[str, int] | None, + chart_type: str | None, +) -> str: + if source_xml_kind == "grpSp": + return "group" + if source_xml_kind == "cxnSp": + return "connector" + if table_dimensions is not None: + return "table" + if chart_type is not None: + return "chart" + if source_xml_kind == "pic" or any( + etree.QName(child).localname == "blipFill" for child in element + ): + return "picture" + if placeholder_type is not None: + return "placeholder" + if field_types: + return "field" + if text_runs: + return "text" + if source_xml_kind == "sp": + return "shape" + return "graphic_frame" + + +def _subtype( + kind: str, + element: etree._Element, + placeholder_type: str | None, + chart_type: str | None, +) -> str | None: + if placeholder_type is not None: + return placeholder_type + if chart_type is not None: + return chart_type + geometry = element.find(f".//{{{A_NS}}}prstGeom") + if geometry is not None and geometry.get("prst"): + return str(geometry.get("prst")) + if kind == "picture": + return "embedded-raster" + return None + + +def _property_container(element: etree._Element) -> etree._Element | None: + for child in element: + if etree.QName(child).localname in {"spPr", "grpSpPr", "xfrm"}: + return child + return None + + +def _xfrm(element: etree._Element) -> etree._Element | None: + container = _property_container(element) + if container is None: + return None + if etree.QName(container).localname == "xfrm": + return container + for child in container: + if etree.QName(child).localname == "xfrm": + return child + return None + + +def _bbox(element: etree._Element) -> dict[str, int]: + transform = _xfrm(element) + if transform is None: + return {"x": 0, "y": 0, "width": 0, "height": 0} + offset = transform.find(f"{{{A_NS}}}off") + extent = transform.find(f"{{{A_NS}}}ext") + if offset is None or extent is None: + return {"x": 0, "y": 0, "width": 0, "height": 0} + return { + "x": _required_integer(offset, "x"), + "y": _required_integer(offset, "y"), + "width": _required_integer(extent, "cx", minimum=0), + "height": _required_integer(extent, "cy", minimum=0), + } + + +def _rotation(element: etree._Element) -> str: + transform = _xfrm(element) + raw = transform.get("rot", "0") if transform is not None else "0" + return _decimal_ratio(raw, 60_000) + + +def _hidden(element: etree._Element) -> bool: + nonvisual = next( + (child for child in element.iter() if etree.QName(child).localname == "cNvPr"), + None, + ) + return _boolean(nonvisual.get("hidden")) is True if nonvisual is not None else False + + +def _nonvisual_name(element: etree._Element) -> str: + nonvisual = next( + (child for child in element.iter() if etree.QName(child).localname == "cNvPr"), + None, + ) + return str(nonvisual.get("name", "")) if nonvisual is not None else "" + + +def _placeholder(element: etree._Element) -> tuple[str | None, int | None]: + placeholder = next(iter(element.iter(f"{{{P_NS}}}ph")), None) + if placeholder is None: + return None, None + placeholder_type = str(placeholder.get("type", "body")) + raw_index = placeholder.get("idx") + return placeholder_type, int(raw_index) if raw_index is not None else None + + +def _text_runs(element: etree._Element) -> list[dict[str, Any]]: + runs: list[dict[str, Any]] = [] + for paragraph in element.iter(f"{{{A_NS}}}p"): + paragraph_properties = paragraph.find(f"{{{A_NS}}}pPr") + paragraph_rtl = ( + _boolean(paragraph_properties.get("rtl")) if paragraph_properties is not None else False + ) + for child in paragraph: + local_name = etree.QName(child).localname + if local_name not in {"r", "fld", "br"}: + continue + run_properties = child.find(f"{{{A_NS}}}rPr") + text_element = child.find(f"{{{A_NS}}}t") + text = ( + "\n" + if local_name == "br" + else (text_element.text or "" if text_element is not None else "") + ) + latin = run_properties.find(f"{{{A_NS}}}latin") if run_properties is not None else None + size = run_properties.get("sz") if run_properties is not None else None + rtl_value = ( + _boolean(run_properties.get("rtl")) + if run_properties is not None and run_properties.get("rtl") is not None + else paragraph_rtl + ) + runs.append( + { + "text": text, + "language": run_properties.get("lang") if run_properties is not None else None, + "rtl": bool(rtl_value), + "font_family": latin.get("typeface") if latin is not None else None, + "font_size_pt": _decimal_ratio(size, 100) if size is not None else None, + "bold": _boolean(run_properties.get("b")) + if run_properties is not None + else None, + "italic": _boolean(run_properties.get("i")) + if run_properties is not None + else None, + } + ) + return runs + + +def _paragraph_properties(element: etree._Element) -> list[dict[str, Any]]: + records: list[dict[str, Any]] = [] + for paragraph in element.iter(f"{{{A_NS}}}p"): + properties = paragraph.find(f"{{{A_NS}}}pPr") + bullet: dict[str, Any] | None = None + line_spacing: dict[str, Any] | None = None + if properties is not None: + for child in properties: + local_name = etree.QName(child).localname + if local_name in {"buNone", "buChar", "buAutoNum", "buBlip"}: + bullet = { + "kind": local_name, + "value": child.get("char") or child.get("type"), + } + if local_name == "lnSpc" and len(child): + spacing = child[0] + line_spacing = { + "kind": etree.QName(spacing).localname, + "value": _optional_integer(spacing.get("val")), + } + records.append( + { + "level": _optional_integer(properties.get("lvl")) + if properties is not None + else None, + "rtl": bool(_boolean(properties.get("rtl"))) if properties is not None else False, + "alignment": properties.get("algn") if properties is not None else None, + "margin_left": _optional_integer(properties.get("marL")) + if properties is not None + else None, + "indent": _optional_integer(properties.get("indent")) + if properties is not None + else None, + "tab_stops": [ + { + "position": _required_integer(tab, "pos"), + "alignment": tab.get("algn"), + } + for tab in properties.findall(f".//{{{A_NS}}}tab") + ] + if properties is not None + else [], + "bullet": bullet, + "line_spacing": line_spacing, + } + ) + return records + + +def _table_dimensions(element: etree._Element) -> dict[str, int] | None: + table = element.find(f".//{{{A_NS}}}tbl") + if table is None: + return None + rows = table.findall(f"{{{A_NS}}}tr") + grid = table.find(f"{{{A_NS}}}tblGrid") + columns = grid.findall(f"{{{A_NS}}}gridCol") if grid is not None else [] + return {"rows": len(rows), "columns": len(columns)} + + +def _chart_properties( + element: etree._Element, + relationships: dict[str, Relationship], + parts: dict[str, bytes], +) -> tuple[str | None, dict[str, int] | None]: + chart = element.find(f".//{{{C_NS}}}chart") + if chart is None: + return None, None + relationship = _bound_relationship(chart, relationships) + chart_root = _parse_xml(_required_part(parts, relationship.target), relationship.target) + plot_area = chart_root.find(f".//{{{C_NS}}}plotArea") + chart_types = ( + sorted( + { + etree.QName(child).localname + for child in plot_area + if etree.QName(child).localname.endswith("Chart") + } + ) + if plot_area is not None + else [] + ) + if not chart_types: + raise SceneGraphError( + f"Chart relationship has no supported chart type: /{relationship.target}" + ) + return "+".join(chart_types), { + "series_count": len(chart_root.findall(f".//{{{C_NS}}}ser")), + "category_point_count": len(chart_root.findall(f".//{{{C_NS}}}cat//{{{C_NS}}}pt")), + "value_point_count": len(chart_root.findall(f".//{{{C_NS}}}val//{{{C_NS}}}pt")), + } + + +def _asset_hash( + element: etree._Element, + relationships: dict[str, Relationship], + parts: dict[str, bytes], +) -> str | None: + relationship_ids = { + blip.get(f"{{{R_NS}}}embed", "") + for blip in element.iter(f"{{{A_NS}}}blip") + if blip.get(f"{{{R_NS}}}embed") + } + if not relationship_ids: + return None + if len(relationship_ids) != 1: + raise SceneGraphError("One scene node references more than one embedded asset") + relationship_id = relationship_ids.pop() + relationship = relationships.get(relationship_id) + if relationship is None: + raise SceneGraphError(f"Embedded asset relationship is missing: {relationship_id}") + return f"sha256:{hashlib.sha256(_required_part(parts, relationship.target)).hexdigest()}" + + +def _bound_relationship( + element: etree._Element, + relationships: dict[str, Relationship], +) -> Relationship: + relationship_id = element.get(f"{{{R_NS}}}id", "") + relationship = relationships.get(relationship_id) + if relationship is None: + raise SceneGraphError(f"Node relationship is missing: {relationship_id!r}") + return relationship + + +def _fill(container: etree._Element | None) -> dict[str, Any]: + if container is None: + return {"kind": "inherited", "color": None, "alpha": None} + for child in container: + local_name = etree.QName(child).localname + if local_name not in {"solidFill", "gradFill", "pattFill", "noFill", "blipFill"}: + continue + color = next( + ( + { + "kind": etree.QName(item).localname, + "value": next(iter(item.attrib.values()), None), + } + for item in child + if etree.QName(item).localname + in {"srgbClr", "schemeClr", "scrgbClr", "prstClr", "sysClr"} + ), + None, + ) + alpha = next( + (item.get("val") for item in child.iter(f"{{{A_NS}}}alpha") if item.get("val")), + None, + ) + return {"kind": local_name, "color": color, "alpha": alpha} + return {"kind": "inherited", "color": None, "alpha": None} + + +def _opacity(fill: dict[str, Any]) -> str: + alpha = fill.get("alpha") + return _decimal_ratio(str(alpha), 100_000) if alpha is not None else "1" + + +def _stroke(container: etree._Element | None) -> dict[str, Any]: + line = container.find(f"{{{A_NS}}}ln") if container is not None else None + if line is None: + return {"present": False, "width_emu": None, "dash": None} + dash = line.find(f"{{{A_NS}}}prstDash") + return { + "present": line.find(f"{{{A_NS}}}noFill") is None, + "width_emu": _optional_integer(line.get("w")), + "dash": dash.get("val") if dash is not None else None, + } + + +def _has_shadow(container: etree._Element | None) -> bool: + return container is not None and any( + etree.QName(child).localname in {"outerShdw", "innerShdw"} for child in container.iter() + ) + + +def _crop(element: etree._Element) -> dict[str, int] | None: + source = element.find(f".//{{{A_NS}}}srcRect") + if source is None: + return None + return {name: _optional_integer(source.get(name)) or 0 for name in ("l", "t", "r", "b")} + + +def _crop_to_shape(element: etree._Element) -> bool: + geometry = element.find(f".//{{{A_NS}}}prstGeom") + return geometry is not None and geometry.get("prst", "rect") != "rect" + + +def _hyperlinks( + element: etree._Element, + relationships: dict[str, Relationship], +) -> list[str]: + targets: set[str] = set() + for hyperlink in element.iter(f"{{{A_NS}}}hlinkClick"): + relationship_id = hyperlink.get(f"{{{R_NS}}}id") + if relationship_id is None: + continue + relationship = relationships.get(relationship_id) + if relationship is None: + raise SceneGraphError(f"Hyperlink relationship is missing: {relationship_id}") + targets.add(f"/{relationship.target}") + return sorted(targets) + + +def _required_integer( + element: etree._Element, + attribute: str, + *, + minimum: int | None = None, +) -> int: + raw = element.get(attribute) + if raw is None: + raise SceneGraphError(f"Required integer attribute is missing: {attribute}") + try: + value = int(raw) + except ValueError as exc: + raise SceneGraphError(f"Invalid integer attribute {attribute}: {raw!r}") from exc + if minimum is not None and value < minimum: + raise SceneGraphError(f"Integer attribute {attribute} is below {minimum}: {value}") + return value + + +def _optional_integer(raw: str | None) -> int | None: + if raw is None: + return None + try: + return int(raw) + except ValueError as exc: + raise SceneGraphError(f"Invalid integer value: {raw!r}") from exc + + +def _decimal_ratio(raw: str, denominator: int) -> str: + try: + value = Decimal(raw) / Decimal(denominator) + except Exception as exc: + raise SceneGraphError(f"Invalid exact decimal input: {raw!r}") from exc + rendered = format(value, "f").rstrip("0").rstrip(".") + return rendered if rendered not in {"", "-0"} else "0" + + +def _boolean(raw: str | None) -> bool | None: + if raw is None: + return None + if raw in {"1", "true", "on"}: + return True + if raw in {"0", "false", "off"}: + return False + raise SceneGraphError(f"Invalid OOXML boolean value: {raw!r}") + + +def _namespace(qname: str) -> str: + return qname[1 : qname.index("}")] if qname.startswith("{") else "" diff --git a/acidslide-v1/grader/acidslide/schema_validate.py b/acidslide-v1/grader/acidslide/schema_validate.py index 6a91ea5..ac1b218 100644 --- a/acidslide-v1/grader/acidslide/schema_validate.py +++ b/acidslide-v1/grader/acidslide/schema_validate.py @@ -1,21 +1,32 @@ -"""Stage 0.5: ECMA-376 schema validation against Transitional XSD schemas.""" +"""Stage 0.5: fail-closed ECMA-376 Transitional XSD validation.""" from __future__ import annotations +import json import zipfile from functools import lru_cache -from pathlib import Path +from typing import TYPE_CHECKING, Any, cast from lxml import etree +from acidslide.mce import ( + MCEProfileError, + load_understood_namespaces, + preprocess_markup_compatibility, +) from acidslide.models import SchemaValidationResult +from acidslide.resources import resolve_normative_schema_file, resolve_schema_dir -# Namespace → XSD file mapping for PresentationML parts -NS_TO_XSD: dict[str, str] = { - "http://schemas.openxmlformats.org/presentationml/2006/main": "pml.xsd", - "http://schemas.openxmlformats.org/drawingml/2006/main": "dml-main.xsd", - "http://schemas.openxmlformats.org/drawingml/2006/chart": "dml-chart.xsd", -} +if TYPE_CHECKING: + from collections.abc import Iterable + from pathlib import Path + +CONTENT_TYPES_PART = "[Content_Types].xml" +CONTENT_TYPES_NAMESPACE = "http://schemas.openxmlformats.org/package/2006/content-types" +PRESENTATION_NAMESPACE = "http://schemas.openxmlformats.org/presentationml/2006/main" +DEFAULT_CONTENT_TYPE = f"{{{CONTENT_TYPES_NAMESPACE}}}Default" +OVERRIDE_CONTENT_TYPE = f"{{{CONTENT_TYPES_NAMESPACE}}}Override" +SLIDE_SIZE = (12192000, 6858000) def _hardened_parser() -> etree.XMLParser: @@ -28,83 +39,191 @@ def _hardened_parser() -> etree.XMLParser: ) -@lru_cache(maxsize=16) -def _load_xsd(xsd_path: str) -> etree.XMLSchema | None: - """Load and cache an XSD schema. Returns None if loading fails.""" - try: - doc = etree.parse(xsd_path, parser=_hardened_parser()) - return etree.XMLSchema(doc) - except Exception: - return None +@lru_cache(maxsize=32) +def _load_xsd(xsd_path: str) -> etree.XMLSchema: + """Load and cache an XSD schema, surfacing configuration failures.""" + doc = etree.parse(xsd_path, parser=_hardened_parser()) + return etree.XMLSchema(doc) def validate_schema( pptx_path: Path, schema_dir: Path | None = None, + *, + mce_profile_path: Path | None = None, + root_map_path: Path | None = None, ) -> SchemaValidationResult: - """Validate .pptx content against ECMA-376 Transitional XSD schemas. + """Validate every relevant PresentationML XML part under the frozen profiles. - Non-blocking: schema-invalid files are not rejected, but violations - are reported in the grading result. + A relevant part with no exact ``(content type, root QName)`` mapping makes + validation incomplete. No namespace-only fallback or silent skip is + permitted in an official run. """ + configuration_errors: list[str] = [] violations: list[str] = [] - - if schema_dir is None: - base = Path(__file__).parent.parent.parent.parent - schema_dir = base / "schemas" / "ecma-376" / "xsd-transitional" - - if not schema_dir.exists(): - return SchemaValidationResult( - valid=True, - violations=["ECMA-376 XSD schemas not found — skipping validation"], + try: + resolved_schema_dir = resolve_schema_dir(schema_dir) + resolved_mce_profile = resolve_normative_schema_file( + "mce-profile-v1.json", mce_profile_path ) - + resolved_root_map = resolve_normative_schema_file("schema-root-map-v1.json", root_map_path) + understood_namespaces = load_understood_namespaces(resolved_mce_profile) + root_map = _load_root_map(resolved_root_map) + except (FileNotFoundError, MCEProfileError, OSError, ValueError, json.JSONDecodeError) as exc: + return SchemaValidationResult(valid=False, performed=False, violations=[str(exc)]) + + relevant_parts = 0 + validated_parts = 0 try: - with zipfile.ZipFile(pptx_path, "r") as zf: - parser = _hardened_parser() + with zipfile.ZipFile(pptx_path, "r") as package: + try: + defaults, overrides = _content_types(package) + except (KeyError, ValueError, etree.XMLSyntaxError) as exc: + return SchemaValidationResult( + valid=False, + performed=False, + violations=[f"Invalid [Content_Types].xml: {exc}"], + ) - for name in zf.namelist(): - if not _should_validate(name): + parser = _hardened_parser() + for name in package.namelist(): + if not _is_relevant_part(name): continue - + relevant_parts += 1 try: - xml_bytes = zf.read(name) - tree = etree.fromstring(xml_bytes, parser=parser) - - # Find the root element's namespace - root_ns = _get_root_namespace(tree) - xsd_file = NS_TO_XSD.get(root_ns) + original_bytes = package.read(name) + tree = etree.fromstring(original_bytes, parser=parser) + evidence: list[dict[str, str]] = [] + preprocess_markup_compatibility( + tree, + understood_namespaces, + preserved_evidence=evidence, + ) + except etree.XMLSyntaxError as exc: + violations.append(f"{name}: XML syntax error — {exc}") + continue + except MCEProfileError as exc: + violations.append(f"{name}: MCE preprocessing error — {exc}") + continue - if xsd_file: - xsd_path = schema_dir / xsd_file - if xsd_path.exists(): - schema = _load_xsd(str(xsd_path)) - if schema and not schema.validate(tree): - for err in schema.error_log: - violations.append(f"{name}:{err.line}: {err.message}") + content_type = _content_type_for(name, defaults, overrides) + if content_type is None: + violations.append(f"{name}: no package content type is declared") + continue + key = (content_type, str(tree.tag)) + xsd_file = root_map.get(key) + if xsd_file is None: + violations.append( + f"{name}: unmapped relevant XML part: content_type={content_type!r}, " + f"root={str(tree.tag)!r}" + ) + continue - except etree.XMLSyntaxError as e: - violations.append(f"{name}: XML syntax error — {e}") + xsd_path = resolved_schema_dir / xsd_file + if not xsd_path.is_file(): + configuration_errors.append(f"Required XSD is missing: {xsd_path}") + continue + try: + schema = _load_xsd(str(xsd_path)) + except (OSError, etree.Error) as exc: + configuration_errors.append(f"Could not load {xsd_path.name}: {exc}") + continue + validated_parts += 1 + if not schema.validate(tree): + for error in cast("Iterable[Any]", schema.error_log): + violations.append(f"{name}:{error.line}: {error.message}") + if name == "ppt/presentation.xml": + violations.extend(_presentation_semantic_violations(tree)) except zipfile.BadZipFile: violations.append("Invalid ZIP structure") - except Exception as e: - violations.append(f"Schema validation error: {e}") + except (OSError, etree.Error) as exc: + violations.append(f"Schema validation error: {exc}") + + if relevant_parts == 0: + configuration_errors.append("No relevant PresentationML XML parts were found") + if validated_parts != relevant_parts: + configuration_errors.append( + f"Schema validation incomplete: validated {validated_parts} of {relevant_parts} " + "relevant XML parts" + ) + performed = ( + relevant_parts > 0 and validated_parts == relevant_parts and not configuration_errors + ) return SchemaValidationResult( - valid=len(violations) == 0, - violations=violations, + valid=performed and not violations, + performed=performed, + violations=[*configuration_errors, *violations], ) -def _should_validate(name: str) -> bool: - """Check if a ZIP entry should be schema-validated.""" +def _load_root_map(path: Path) -> dict[tuple[str, str], str]: + document = json.loads(path.read_text(encoding="utf-8")) + if document.get("mapping_id") != "acidslide-schema-root-map-v1": + raise ValueError(f"Unsupported schema/root mapping: {path}") + mapping: dict[tuple[str, str], str] = {} + for entry in document.get("entries", []): + key = (entry["content_type"], entry["root_qname"]) + if key in mapping: + raise ValueError(f"Duplicate schema/root mapping entry: {key}") + mapping[key] = entry["xsd"] + if not mapping: + raise ValueError(f"Schema/root mapping has no entries: {path}") + return mapping + + +def _content_types(package: zipfile.ZipFile) -> tuple[dict[str, str], dict[str, str]]: + root = etree.fromstring(package.read(CONTENT_TYPES_PART), parser=_hardened_parser()) + if str(root.tag) != f"{{{CONTENT_TYPES_NAMESPACE}}}Types": + raise ValueError(f"unexpected root {root.tag!r}") + defaults: dict[str, str] = {} + overrides: dict[str, str] = {} + for child in root: + if child.tag == DEFAULT_CONTENT_TYPE: + extension = child.get("Extension") + content_type = child.get("ContentType") + if not extension or not content_type or extension in defaults: + raise ValueError("duplicate or malformed Default content type") + defaults[extension.lower()] = content_type + elif child.tag == OVERRIDE_CONTENT_TYPE: + part_name = child.get("PartName") + content_type = child.get("ContentType") + if not part_name or not part_name.startswith("/") or not content_type: + raise ValueError("malformed Override content type") + normalized = part_name[1:] + if normalized in overrides: + raise ValueError(f"duplicate Override content type for {normalized}") + overrides[normalized] = content_type + else: + raise ValueError(f"unexpected child {child.tag!r}") + return defaults, overrides + + +def _content_type_for(name: str, defaults: dict[str, str], overrides: dict[str, str]) -> str | None: + if name in overrides: + return overrides[name] + extension = name.rsplit(".", 1)[-1].lower() if "." in name else "" + return defaults.get(extension) + + +def _is_relevant_part(name: str) -> bool: return name.startswith("ppt/") and name.endswith(".xml") and "/_rels/" not in name -def _get_root_namespace(tree: etree._Element) -> str: - """Extract the namespace URI from the root element's tag.""" - tag = tree.tag - if tag.startswith("{"): - return tag[1 : tag.index("}")] - return "" +def _presentation_semantic_violations(tree: etree._Element) -> list[str]: + """Enforce v1 presentation invariants that ECMA-376 leaves variable.""" + slide_sizes = tree.findall(f"{{{PRESENTATION_NAMESPACE}}}sldSz") + if len(slide_sizes) != 1: + return [f"ppt/presentation.xml: expected exactly one p:sldSz; found {len(slide_sizes)}"] + slide_size = slide_sizes[0] + try: + actual = (int(slide_size.get("cx", "")), int(slide_size.get("cy", ""))) + except ValueError: + return ["ppt/presentation.xml: p:sldSz cx/cy must be integer EMU values"] + if actual != SLIDE_SIZE: + return [ + "ppt/presentation.xml: p:sldSz must be exactly " + f"cx={SLIDE_SIZE[0]}, cy={SLIDE_SIZE[1]} EMU; found cx={actual[0]}, cy={actual[1]}" + ] + return [] diff --git a/acidslide-v1/grader/acidslide/source_tree.py b/acidslide-v1/grader/acidslide/source_tree.py new file mode 100644 index 0000000..5c41161 --- /dev/null +++ b/acidslide-v1/grader/acidslide/source_tree.py @@ -0,0 +1,339 @@ +"""Deterministic construction and verification of the frozen grader source tree.""" + +from __future__ import annotations + +import hashlib +import json +import os +import stat +import tarfile +import unicodedata +from dataclasses import dataclass +from pathlib import Path, PurePosixPath +from typing import Any + +import rfc8785 + +_MANIFEST_FIELDS = { + "schema_version", + "manifest_id", + "source_tree_profile_sha256", + "root", + "entries", +} +_ENTRY_FIELDS = {"path", "byte_length", "sha256", "executable"} +_LOGICAL_ROOT = "acidslide-v1/grader" + + +class GraderSourceTreeError(RuntimeError): + """The grader source tree cannot be trusted under the frozen v1 profile.""" + + +@dataclass(frozen=True) +class GraderSourceTreeIdentity: + """Content identities proven by a source-tree reconstruction.""" + + manifest_sha256: str + profile_sha256: str + entry_count: int + + +def build_grader_source_tree_manifest(root: Path, profile_path: Path) -> dict[str, Any]: + """Build the self-hash-free manifest object for a directory without writing it.""" + profile_sha256 = _load_profile(profile_path) + entries, directories = _entries_from_directory(root) + if not entries: + raise GraderSourceTreeError("grader source tree contains no files") + _validate_directory_inventory(directories, {entry["path"] for entry in entries}) + return { + "schema_version": "1.0", + "manifest_id": "acidslide-grader-source-tree-manifest-v1", + "source_tree_profile_sha256": profile_sha256, + "root": _LOGICAL_ROOT, + "entries": entries, + } + + +def verify_grader_source_tree( + source: Path, + manifest_path: Path, + profile_path: Path, +) -> GraderSourceTreeIdentity: + """Reconstruct a directory or release tar and require exact manifest equality.""" + profile_sha256 = _load_profile(profile_path) + manifest_bytes, manifest = _load_manifest(manifest_path) + if manifest.get("source_tree_profile_sha256") != profile_sha256: + raise GraderSourceTreeError("grader source-tree manifest is bound to another profile") + expected_entries = _validate_manifest_entries(manifest.get("entries")) + expected_by_path = {entry["path"]: entry for entry in expected_entries} + + if source.is_dir(): + actual_entries, directories = _entries_from_directory(source) + _validate_directory_inventory(directories, set(expected_by_path)) + elif source.is_file(): + actual_entries = _entries_from_tar(source, expected_by_path) + else: + raise GraderSourceTreeError(f"grader source tree is unavailable: {source}") + if actual_entries != expected_entries: + raise GraderSourceTreeError("grader source tree does not match its frozen manifest") + return GraderSourceTreeIdentity( + manifest_sha256=f"sha256:{hashlib.sha256(manifest_bytes).hexdigest()}", + profile_sha256=profile_sha256, + entry_count=len(actual_entries), + ) + + +def _load_profile(path: Path) -> str: + try: + raw = path.read_bytes() + profile = json.loads(raw) + except OSError as exc: + raise GraderSourceTreeError(f"grader source-tree profile is unavailable: {path}") from exc + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise GraderSourceTreeError("grader source-tree profile is not valid JSON") from exc + if not isinstance(profile, dict): + raise GraderSourceTreeError("grader source-tree profile must be an object") + if ( + profile.get("schema_version") != "1.0" + or profile.get("profile_id") != "acidslide-grader-source-tree-v1" + or profile.get("root") != _LOGICAL_ROOT + or profile.get("manifest_canonicalization") != "RFC8785-JCS" + or profile.get("manifest_digest") != "SHA-256-lowercase-hex-prefixed" + or profile.get("path_order") != "ascending-Unicode-code-point" + ): + raise GraderSourceTreeError("grader source-tree profile identity is unsupported") + return f"sha256:{hashlib.sha256(raw).hexdigest()}" + + +def _load_manifest(path: Path) -> tuple[bytes, dict[str, Any]]: + try: + raw = path.read_bytes() + manifest = json.loads(raw) + except OSError as exc: + raise GraderSourceTreeError(f"grader source-tree manifest is unavailable: {path}") from exc + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise GraderSourceTreeError("grader source-tree manifest is not valid JSON") from exc + if not isinstance(manifest, dict) or set(manifest) != _MANIFEST_FIELDS: + raise GraderSourceTreeError("grader source-tree manifest has missing or unsupported fields") + if ( + manifest.get("schema_version") != "1.0" + or manifest.get("manifest_id") != "acidslide-grader-source-tree-manifest-v1" + or manifest.get("root") != _LOGICAL_ROOT + ): + raise GraderSourceTreeError("grader source-tree manifest identity is unsupported") + try: + canonical = rfc8785.dumps(manifest) + except rfc8785.CanonicalizationError as exc: + raise GraderSourceTreeError("grader source-tree manifest cannot be canonicalized") from exc + if raw != canonical: + raise GraderSourceTreeError("grader source-tree manifest is not RFC 8785 canonical JSON") + return raw, manifest + + +def _validate_manifest_entries(value: object) -> list[dict[str, Any]]: + if not isinstance(value, list) or not value: + raise GraderSourceTreeError("grader source-tree manifest has no entries") + entries: list[dict[str, Any]] = [] + paths: list[str] = [] + casefolded: set[str] = set() + for raw_entry in value: + if not isinstance(raw_entry, dict) or set(raw_entry) != _ENTRY_FIELDS: + raise GraderSourceTreeError("grader source-tree entry has invalid fields") + path = _validate_relative_path(raw_entry.get("path")) + byte_length = raw_entry.get("byte_length") + digest = raw_entry.get("sha256") + executable = raw_entry.get("executable") + if not isinstance(byte_length, int) or isinstance(byte_length, bool) or byte_length < 0: + raise GraderSourceTreeError(f"grader source-tree byte length is invalid: {path}") + if ( + not isinstance(digest, str) + or len(digest) != 71 + or not digest.startswith("sha256:") + or any(character not in "0123456789abcdef" for character in digest[7:]) + ): + raise GraderSourceTreeError(f"grader source-tree digest is invalid: {path}") + if not isinstance(executable, bool): + raise GraderSourceTreeError(f"grader source-tree executable flag is invalid: {path}") + folded = path.casefold() + if folded in casefolded: + raise GraderSourceTreeError(f"grader source-tree path collision: {path}") + casefolded.add(folded) + paths.append(path) + entries.append(dict(raw_entry)) + if paths != sorted(paths) or len(paths) != len(set(paths)): + raise GraderSourceTreeError("grader source-tree entries are not uniquely code-point sorted") + return entries + + +def _entries_from_directory(root: Path) -> tuple[list[dict[str, Any]], set[str]]: + try: + root_stat = root.lstat() + except OSError as exc: + raise GraderSourceTreeError(f"grader source root is unavailable: {root}") from exc + if stat.S_ISLNK(root_stat.st_mode) or not stat.S_ISDIR(root_stat.st_mode): + raise GraderSourceTreeError("grader source root must be a real directory") + entries: list[dict[str, Any]] = [] + directories: set[str] = set() + + def visit(directory: Path, relative_parent: PurePosixPath) -> None: + try: + children = sorted(os.scandir(directory), key=lambda item: item.name) + except OSError as exc: + raise GraderSourceTreeError( + f"grader source directory is unreadable: {directory}" + ) from exc + for child in children: + relative = relative_parent / child.name + path = _validate_relative_path(relative.as_posix()) + try: + metadata = child.stat(follow_symlinks=False) + except OSError as exc: + raise GraderSourceTreeError(f"grader source entry is unreadable: {path}") from exc + if stat.S_ISLNK(metadata.st_mode): + raise GraderSourceTreeError(f"grader source symlink is prohibited: {path}") + if stat.S_ISDIR(metadata.st_mode): + directories.add(path) + visit(Path(child.path), relative) + elif stat.S_ISREG(metadata.st_mode): + entries.append(_file_entry(Path(child.path), path, metadata)) + else: + raise GraderSourceTreeError(f"grader source special file is prohibited: {path}") + + visit(root, PurePosixPath()) + entries.sort(key=lambda entry: entry["path"]) + _validate_actual_paths(entries) + return entries, directories + + +def _file_entry(path: Path, relative: str, initial: os.stat_result) -> dict[str, Any]: + if initial.st_nlink != 1: + raise GraderSourceTreeError(f"grader source hard link is prohibited: {relative}") + flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) + try: + descriptor = os.open(path, flags) + except OSError as exc: + raise GraderSourceTreeError(f"grader source file is unreadable: {relative}") from exc + digest = hashlib.sha256() + byte_length = 0 + try: + opened = os.fstat(descriptor) + if not stat.S_ISREG(opened.st_mode) or opened.st_nlink != 1: + raise GraderSourceTreeError(f"grader source file changed type: {relative}") + while block := os.read(descriptor, 1024 * 1024): + byte_length += len(block) + digest.update(block) + final = os.fstat(descriptor) + finally: + os.close(descriptor) + if ( + opened.st_dev != initial.st_dev + or opened.st_ino != initial.st_ino + or final.st_size != byte_length + or final.st_mtime_ns != opened.st_mtime_ns + ): + raise GraderSourceTreeError(f"grader source file changed during hashing: {relative}") + return { + "path": relative, + "byte_length": byte_length, + "sha256": f"sha256:{digest.hexdigest()}", + "executable": bool(opened.st_mode & 0o111), + } + + +def _entries_from_tar( + archive: Path, expected_by_path: dict[str, dict[str, Any]] +) -> list[dict[str, Any]]: + entries: list[dict[str, Any]] = [] + directories: set[str] = set() + root_prefix = f"{_LOGICAL_ROOT}/" + try: + with tarfile.open(archive, mode="r:*") as package: + for member in package: + member_name = _validate_archive_path(member.name) + if member_name == _LOGICAL_ROOT and member.isdir(): + continue + if not member_name.startswith(root_prefix): + raise GraderSourceTreeError( + f"grader archive entry is outside its root: {member_name}" + ) + relative = _validate_relative_path(member_name[len(root_prefix) :]) + if member.issym() or member.islnk(): + raise GraderSourceTreeError(f"grader archive link is prohibited: {relative}") + if member.isdir(): + directories.add(relative) + continue + if not member.isfile(): + raise GraderSourceTreeError( + f"grader archive special entry is prohibited: {relative}" + ) + expected = expected_by_path.get(relative) + if expected is None: + raise GraderSourceTreeError( + f"grader archive contains an extra file: {relative}" + ) + if member.size != expected["byte_length"]: + raise GraderSourceTreeError(f"grader archive file length mismatch: {relative}") + stream = package.extractfile(member) + if stream is None: + raise GraderSourceTreeError(f"grader archive file is unreadable: {relative}") + digest = hashlib.sha256() + byte_length = 0 + while block := stream.read(1024 * 1024): + byte_length += len(block) + digest.update(block) + entries.append( + { + "path": relative, + "byte_length": byte_length, + "sha256": f"sha256:{digest.hexdigest()}", + "executable": bool(member.mode & 0o111), + } + ) + except (OSError, tarfile.TarError) as exc: + raise GraderSourceTreeError("grader source archive is not a valid tar") from exc + entries.sort(key=lambda entry: entry["path"]) + _validate_actual_paths(entries) + _validate_directory_inventory(directories, set(expected_by_path)) + return entries + + +def _validate_relative_path(value: object) -> str: + if not isinstance(value, str) or not value: + raise GraderSourceTreeError("grader source path must be a nonempty string") + if unicodedata.normalize("NFC", value) != value: + raise GraderSourceTreeError(f"grader source path is not NFC: {value!r}") + try: + value.encode("utf-8", errors="strict") + except UnicodeEncodeError as exc: + raise GraderSourceTreeError("grader source path is not UTF-8 encodable") from exc + if ( + value.startswith("/") + or "\\" in value + or "\0" in value + or "//" in value + or any(segment in {"", ".", ".."} for segment in value.split("/")) + ): + raise GraderSourceTreeError(f"grader source path is unsafe: {value!r}") + return value + + +def _validate_archive_path(value: str) -> str: + path = _validate_relative_path(value.rstrip("/")) + if value.endswith("//"): + raise GraderSourceTreeError(f"grader archive path is unsafe: {value!r}") + return path + + +def _validate_actual_paths(entries: list[dict[str, Any]]) -> None: + paths = [entry["path"] for entry in entries] + if len(paths) != len(set(paths)) or len(paths) != len({path.casefold() for path in paths}): + raise GraderSourceTreeError("grader source contains duplicate or case-fold-colliding paths") + + +def _validate_directory_inventory(directories: set[str], file_paths: set[str]) -> None: + for directory in directories: + prefix = f"{directory}/" + if not any(path.startswith(prefix) for path in file_paths): + raise GraderSourceTreeError( + f"grader source contains an unmanifested empty directory: {directory}" + ) diff --git a/acidslide-v1/grader/hatch_build.py b/acidslide-v1/grader/hatch_build.py new file mode 100644 index 0000000..80d752e --- /dev/null +++ b/acidslide-v1/grader/hatch_build.py @@ -0,0 +1,34 @@ +"""Hatch hook that makes wheels self-contained in source and sdist builds.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + + +class CustomBuildHook(BuildHookInterface): + """Include benchmark and schema trees from either repository or sdist layout.""" + + def initialize(self, version: str, build_data: dict[str, Any]) -> None: + project_root = Path(self.root) + force_include: dict[str, str] = build_data["force_include"] + for name in ("benchmark", "schemas"): + sdist_source = project_root / "acidslide" / "data" / name + if sdist_source.is_dir(): + continue + + repository_source = project_root.parent / name + if not repository_source.is_dir(): + msg = f"Required AcidSlide package data is missing: {name}" + raise FileNotFoundError(msg) + force_include[str(repository_source)] = f"acidslide/data/{name}" + + # The source tree keeps the public release keyring beside benchmark/. + # A frozen release wheel mirrors it beside the packaged benchmark so + # local signature verification does not depend on repository layout. + packaged_keyring = project_root / "acidslide" / "data" / "RELEASE_KEYS.json" + repository_keyring = project_root.parent / "RELEASE_KEYS.json" + if not packaged_keyring.is_file() and repository_keyring.is_file(): + force_include[str(repository_keyring)] = "acidslide/data/RELEASE_KEYS.json" diff --git a/acidslide-v1/grader/pyproject.toml b/acidslide-v1/grader/pyproject.toml index bbb5855..5a9470e 100644 --- a/acidslide-v1/grader/pyproject.toml +++ b/acidslide-v1/grader/pyproject.toml @@ -10,13 +10,17 @@ readme = "README.md" requires-python = ">=3.12" license = "Apache-2.0" dependencies = [ - "lxml>=5.0", - "Pillow>=10.0", + "cryptography>=45.0", + "lxml>=6.1.0", + "Pillow>=12.3.0", + "pypdf>=6.4.0", "numpy>=1.26", "scikit-image>=0.22", "pydantic>=2.0", - "click>=8.0", + "click>=8.3.3", + "jsonschema>=4.23", "rich>=13.0", + "rfc8785>=0.1.4", "PyYAML>=6.0", ] @@ -26,6 +30,9 @@ dev = [ "pytest-cov>=5.0", "ruff>=0.5", "mypy>=1.10", + "lxml-stubs>=0.5.1", + "pip-audit>=2.10", + "types-jsonschema>=4.26.0.20260518", ] [project.scripts] @@ -41,3 +48,17 @@ select = ["E", "F", "I", "N", "W", "UP", "B", "SIM", "TCH"] [tool.mypy] python_version = "3.12" strict = true + +[tool.pytest.ini_options] +addopts = "--strict-config --strict-markers" + +[tool.hatch.build.targets.sdist.force-include] +"../benchmark" = "acidslide/data/benchmark" +"../schemas" = "acidslide/data/schemas" + +[tool.hatch.build.targets.sdist.hooks.custom] + +[tool.hatch.build.targets.wheel] +packages = ["acidslide"] + +[tool.hatch.build.targets.wheel.hooks.custom] diff --git a/acidslide-v1/grader/tests/test_checklist.py b/acidslide-v1/grader/tests/test_checklist.py index ca879d0..bd411c9 100644 --- a/acidslide-v1/grader/tests/test_checklist.py +++ b/acidslide-v1/grader/tests/test_checklist.py @@ -1,11 +1,10 @@ """Tests for the checklist loader.""" -import tempfile from pathlib import Path import pytest -from acidslide.checklist import ChecklistItem, load_checklist +from acidslide.checklist import load_checklist @pytest.fixture diff --git a/acidslide-v1/grader/tests/test_cli.py b/acidslide-v1/grader/tests/test_cli.py new file mode 100644 index 0000000..534d482 --- /dev/null +++ b/acidslide-v1/grader/tests/test_cli.py @@ -0,0 +1,277 @@ +"""Tests for CLI serialization, exit status, and export display.""" + +from __future__ import annotations + +import json +from dataclasses import replace +from typing import TYPE_CHECKING, Any + +from click.testing import CliRunner +from test_models import _environment_attestation +from test_models import _report as _diagnostic_report +from test_pipeline import _benchmark, _cohort, _context, _patch_successful_stages, _submission + +from acidslide.cli import main +from acidslide.models import ( + DisqualificationState, + GradeReport, + QuarantineResult, + SchemaValidationResult, + SlideExport, +) + +if TYPE_CHECKING: + from pathlib import Path + + import pytest + + +def _report(*, complete: bool) -> GradeReport: + report = _diagnostic_report() + if not complete: + return report + return replace( + report, + schema_valid=True, + visual_verification_performed=True, + verification_complete=True, + scoring_completed=True, + disqualification_state=DisqualificationState.NONE, + ineligibility_reasons=[], + fidelity_score=1.0, + campaign_contribution=1.0, + passed_items=1, + total_items=1, + deck_passed=True, + eligible=True, + tier_scores={ + "level_1": {"fidelity_score": 1.0, "passed": 1, "total": 1}, + "level_2": None, + "level_3": None, + }, + schema_violations=[], + verification_errors=[], + verified_metrics=report.verified_metrics + | { + "schema_valid": True, + "visual_verification_performed": True, + "verification_complete": True, + }, + ) + + +def _context_file(path: Path, submission: Path) -> tuple[Path, dict[str, Any]]: + environment_attestation = _environment_attestation() + context_path = path / "artifact-context.json" + context_path.write_text( + json.dumps(_context(submission, environment_attestation).as_dict()), + encoding="utf-8", + ) + return context_path, environment_attestation + + +def test_grade_writes_real_html(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: + submission = _submission(tmp_path / "submission.pptx") + context_path, _environment = _context_file(tmp_path, submission) + output = tmp_path / "report.html" + monkeypatch.setattr("acidslide.pipeline.run_pipeline", lambda **_kwargs: _report(complete=True)) + + result = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--artifact-context", + str(context_path), + "--format", + "html", + "-o", + str(output), + ], + ) + + assert result.exit_code == 0 + assert output.read_text(encoding="utf-8").startswith("") + + +def test_grade_incomplete_report_exits_two(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: + submission = _submission(tmp_path / "submission.pptx") + context_path, _environment = _context_file(tmp_path, submission) + monkeypatch.setattr( + "acidslide.pipeline.run_pipeline", + lambda **_kwargs: _report(complete=False), + ) + + result = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--artifact-context", + str(context_path), + ], + ) + + assert result.exit_code == 2 + assert "INCOMPLETE" in result.output + assert "schema_validation_failed" in result.output + + +def test_grade_requires_artifact_context(tmp_path: Path) -> None: + submission = _submission(tmp_path / "submission.pptx") + + result = CliRunner().invoke(main, ["grade", str(submission), "--tier", "1"]) + + assert result.exit_code == 2 + assert "Missing option '--artifact-context'" in result.output + + +def test_grade_rejects_missing_and_unknown_context_fields(tmp_path: Path) -> None: + submission = _submission(tmp_path / "submission.pptx") + context_path = tmp_path / "artifact-context.json" + context_path.write_text("{}", encoding="utf-8") + + missing = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--artifact-context", + str(context_path), + ], + ) + assert missing.exit_code == 2 + assert "missing field(s)" in missing.output + + environment_attestation = _environment_attestation() + payload = _context(submission, environment_attestation).as_dict() | {"invented": True} + context_path.write_text(json.dumps(payload), encoding="utf-8") + unknown = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--artifact-context", + str(context_path), + ], + ) + assert unknown.exit_code == 2 + assert "unknown field(s): invented" in unknown.output + + +def test_grade_real_local_pipeline_accepts_verified_context( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + benchmark = _benchmark(tmp_path / "benchmark") + submission = _submission(tmp_path / "submission.pptx") + context_path, environment_attestation = _context_file(tmp_path, submission) + _patch_successful_stages(monkeypatch) + monkeypatch.setattr( + "acidslide.pipeline.load_signed_release_provenance", + lambda _benchmark: _cohort(environment_attestation), + ) + + result = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--benchmark-dir", + str(benchmark), + "--artifact-context", + str(context_path), + "--format", + "json", + ], + ) + + assert result.exit_code == 0 + payload = json.loads(result.output) + assert payload["grading_mode"] == "local" + assert payload["verification_complete"] is True + assert payload["eligible"] is False + assert payload["campaign_contribution"] == 0.0 + + +def test_grade_rejects_environment_attestation_jcs_tamper( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + benchmark = _benchmark(tmp_path / "benchmark") + submission = _submission(tmp_path / "submission.pptx") + environment_attestation = _environment_attestation() + context = _context(submission, environment_attestation) + context_payload = context.as_dict() + context_payload["environment_attestation"] = environment_attestation | {"tampered": True} + context_path = tmp_path / "artifact-context.json" + context_path.write_text(json.dumps(context_payload), encoding="utf-8") + monkeypatch.setattr( + "acidslide.pipeline.load_signed_release_provenance", + lambda _benchmark: _cohort(environment_attestation), + ) + + result = CliRunner().invoke( + main, + [ + "grade", + str(submission), + "--tier", + "1", + "--benchmark-dir", + str(benchmark), + "--artifact-context", + str(context_path), + ], + ) + + assert result.exit_code == 2 + assert "environment attestation payload" in result.output + assert "match the scoring cohort" in result.output + + +def test_export_prints_slide_path_name(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: + submission = tmp_path / "submission.pptx" + submission.write_bytes(b"pptx") + monkeypatch.setattr( + "acidslide.export.export_slides", + lambda _submission, output, **_kwargs: [SlideExport(1, output / "slide-01.png")], + ) + + result = CliRunner().invoke(main, ["export", str(submission), "--outdir", str(tmp_path)]) + + assert result.exit_code == 0 + assert "slide-01.png" in result.output + + +def test_validate_exits_two_when_schema_cannot_run( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + submission = tmp_path / "submission.pptx" + submission.write_bytes(b"pptx") + monkeypatch.setattr( + "acidslide.quarantine.quarantine_check", + lambda _path: QuarantineResult(passed=True), + ) + monkeypatch.setattr( + "acidslide.schema_validate.validate_schema", + lambda _path: SchemaValidationResult( + valid=False, + performed=False, + violations=["schemas unavailable"], + ), + ) + + result = CliRunner().invoke(main, ["validate", str(submission)]) + + assert result.exit_code == 2 + assert "not performed" in result.output + assert "schemas unavailable" in result.output diff --git a/acidslide-v1/grader/tests/test_compare.py b/acidslide-v1/grader/tests/test_compare.py new file mode 100644 index 0000000..ce49728 --- /dev/null +++ b/acidslide-v1/grader/tests/test_compare.py @@ -0,0 +1,76 @@ +"""Tests for render comparison and diff diagnostics.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import numpy as np +from PIL import Image + +from acidslide.compare import compare_slides + +if TYPE_CHECKING: + from pathlib import Path + + +def _image(path: Path, color: tuple[int, int, int], size: tuple[int, int] = (16, 16)) -> None: + Image.new("RGB", size, color).save(path) + + +def test_identical_slides_are_pixel_exact(tmp_path: Path) -> None: + gold = tmp_path / "gold" + submission = tmp_path / "submission" + gold.mkdir() + submission.mkdir() + _image(gold / "slide-01.png", (20, 30, 40)) + _image(submission / "slide-01.png", (20, 30, 40)) + + result = compare_slides(submission, gold) + + assert result[0].pixel_exact is True + assert result[0].ssim == 1.0 + + +def test_missing_submission_slide_scores_zero(tmp_path: Path) -> None: + gold = tmp_path / "gold" + submission = tmp_path / "submission" + gold.mkdir() + submission.mkdir() + _image(gold / "slide-01.png", (20, 30, 40)) + + result = compare_slides(submission, gold) + + assert result[0].ssim == 0.0 + assert result[0].pixel_exact is False + + +def test_dimension_mismatch_fails_without_resizing(tmp_path: Path) -> None: + gold = tmp_path / "gold" + submission = tmp_path / "submission" + diffs = tmp_path / "diffs" + gold.mkdir() + submission.mkdir() + _image(gold / "slide-01.png", (0, 0, 0)) + _image(submission / "slide-01.png", (255, 255, 255), size=(32, 32)) + + result = compare_slides(submission, gold, diffs) + + assert result[0].ssim == 0.0 + assert result[0].pixel_exact is False + assert result[0].diff_path is None + + +def test_diff_uses_signed_arithmetic_before_amplification(tmp_path: Path) -> None: + gold = tmp_path / "gold" + submission = tmp_path / "submission" + diffs = tmp_path / "diffs" + gold.mkdir() + submission.mkdir() + _image(gold / "slide-01.png", (0, 0, 0)) + _image(submission / "slide-01.png", (255, 255, 255)) + + result = compare_slides(submission, gold, diffs) + + assert result[0].diff_path == diffs / "diff-slide-01.png" + with Image.open(result[0].diff_path) as diff: + assert np.array(diff).max() == 255 diff --git a/acidslide-v1/grader/tests/test_evaluate.py b/acidslide-v1/grader/tests/test_evaluate.py index f5f8146..8385f96 100644 --- a/acidslide-v1/grader/tests/test_evaluate.py +++ b/acidslide-v1/grader/tests/test_evaluate.py @@ -2,7 +2,9 @@ from __future__ import annotations -import pytest +from typing import Any + +from lxml import etree from acidslide.checklist import ChecklistItem, FailureMode, Verification from acidslide.evaluate import ( @@ -10,8 +12,8 @@ compute_tier_scores, evaluate_checklist, ) -from acidslide.inspect_ooxml import DeckGraph, SceneObject, SlideGraph, TextRun -from acidslide.models import Severity, VisualComparisonResult +from acidslide.inspect_ooxml import DeckGraph, SceneObject, SlideGraph, TextRun, _parse_shape +from acidslide.models import VisualComparisonResult def _make_item( @@ -22,7 +24,7 @@ def _make_item( severity: str = "critical", method: str = "object_compare", selector: str = "table", - expectation: dict | None = None, + expectation: dict[str, Any] | None = None, failure_mode: FailureMode | None = None, ) -> ChecklistItem: return ChecklistItem( @@ -65,11 +67,44 @@ def _make_deck(slides: list[SlideGraph] | None = None) -> DeckGraph: class TestObjectCompare: + def test_raster_filled_native_shape_is_picture_semantic_equivalent(self) -> None: + shape = etree.fromstring( + b""" + + + """ + ) + slide = _make_slide(objects=[_parse_shape(shape)]) + item = _make_item("s7.pictures", selector="picture", expectation={"min_count": 1}) + + results, _, _ = evaluate_checklist(_make_deck([slide]), [item]) + + assert results[0].items[0].passed is True + + def test_generic_shape_selector_counts_groups_and_descendants(self) -> None: + group = SceneObject( + obj_type="group", + children=[SceneObject(obj_type="shape"), SceneObject(obj_type="shape")], + ) + item = _make_item("s17.shapes", selector="shape", expectation={"min_count": 3}) + + results, _, _ = evaluate_checklist( + _make_deck([_make_slide(objects=[group])]), + [item], + ) + + assert results[0].items[0].passed is True + def test_table_found(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="table", is_table=True, table_rows=3, table_cols=4), - ]) - item = _make_item("s3.table", selector="table", expectation={"exact_count": 1, "required": True}) + slide = _make_slide( + objects=[ + SceneObject(obj_type="table", is_table=True, table_rows=3, table_cols=4), + ] + ) + item = _make_item( + "s3.table", selector="table", expectation={"exact_count": 1, "required": True} + ) deck = _make_deck([slide]) results, _, _ = evaluate_checklist(deck, [item]) @@ -77,32 +112,46 @@ def test_table_found(self) -> None: assert results[0].items[0].passed is True def test_table_missing(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), - ]) - item = _make_item("s3.table", selector="table", expectation={"exact_count": 1, "required": True}) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), + ] + ) + item = _make_item( + "s3.table", selector="table", expectation={"exact_count": 1, "required": True} + ) deck = _make_deck([slide]) results, _, _ = evaluate_checklist(deck, [item]) assert results[0].items[0].passed is False - assert "not found" in results[0].items[0].details.lower() or "Expected" in results[0].items[0].details + assert ( + "not found" in results[0].items[0].details.lower() + or "Expected" in results[0].items[0].details + ) def test_chart_found(self) -> None: - slide = _make_slide(slide_number=4, objects=[ - SceneObject(obj_type="chart", is_chart=True), - ]) - item = _make_item("s4.chart", slide=4, selector="chart", expectation={"exact_count": 1, "required": True}) + slide = _make_slide( + slide_number=4, + objects=[ + SceneObject(obj_type="chart", is_chart=True), + ], + ) + item = _make_item( + "s4.chart", slide=4, selector="chart", expectation={"exact_count": 1, "required": True} + ) deck = _make_deck([slide]) results, _, _ = evaluate_checklist(deck, [item]) assert results[0].items[0].passed is True def test_min_count(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), - SceneObject(obj_type="shape"), - SceneObject(obj_type="shape"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), + SceneObject(obj_type="shape"), + SceneObject(obj_type="shape"), + ] + ) item = _make_item("s1.shapes", selector="shape", expectation={"min_count": 2}) deck = _make_deck([slide]) @@ -112,12 +161,14 @@ def test_min_count(self) -> None: class TestTextMatch: def test_contains_found(self) -> None: - slide = _make_slide(objects=[ - SceneObject( - obj_type="shape", - text_runs=[TextRun(text="Hello World")], - ), - ]) + slide = _make_slide( + objects=[ + SceneObject( + obj_type="shape", + text_runs=[TextRun(text="Hello World")], + ), + ] + ) item = _make_item("s1.text", method="text_match", expectation={"contains": "Hello"}) deck = _make_deck([slide]) @@ -125,9 +176,11 @@ def test_contains_found(self) -> None: assert results[0].items[0].passed is True def test_contains_not_found(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[TextRun(text="Goodbye")]), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape", text_runs=[TextRun(text="Goodbye")]), + ] + ) item = _make_item("s1.text", method="text_match", expectation={"contains": "Hello"}) deck = _make_deck([slide]) @@ -137,9 +190,11 @@ def test_contains_not_found(self) -> None: class TestFieldCheck: def test_slidenum_field_found(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", field_type="slidenum"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape", field_type="slidenum"), + ] + ) item = _make_item("s12.field", method="field_check", expectation={"field_type": "slidenum"}) deck = _make_deck([slide]) @@ -147,9 +202,11 @@ def test_slidenum_field_found(self) -> None: assert results[0].items[0].passed is True def test_slidenum_field_missing(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), + ] + ) item = _make_item("s12.field", method="field_check", expectation={"field_type": "slidenum"}) deck = _make_deck([slide]) @@ -159,9 +216,11 @@ def test_slidenum_field_missing(self) -> None: class TestLayoutCheck: def test_placeholder_found(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", placeholder_type="title"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape", placeholder_type="title"), + ] + ) item = _make_item( "s1.ph", method="layout_check", @@ -174,9 +233,11 @@ def test_placeholder_found(self) -> None: assert results[0].items[0].passed is True def test_placeholder_missing(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), + ] + ) item = _make_item( "s1.ph", method="layout_check", @@ -199,12 +260,17 @@ def test_master_ref_present(self) -> None: class TestAntiCheat: def test_font_policy_pass(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[ - TextRun(text="Hello", font_family="Carlito"), - TextRun(text="World", font_family="Noto Sans"), - ]), - ]) + slide = _make_slide( + objects=[ + SceneObject( + obj_type="shape", + text_runs=[ + TextRun(text="Hello", font_family="Carlito"), + TextRun(text="World", font_family="Noto Sans"), + ], + ), + ] + ) item = _make_item("s1.font", method="anti_cheat", selector="font_policy") deck = _make_deck([slide]) @@ -212,11 +278,16 @@ def test_font_policy_pass(self) -> None: assert results[0].items[0].passed is True def test_font_policy_fail(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[ - TextRun(text="Bad", font_family="Arial"), - ]), - ]) + slide = _make_slide( + objects=[ + SceneObject( + obj_type="shape", + text_runs=[ + TextRun(text="Bad", font_family="Arial"), + ], + ), + ] + ) item = _make_item( "s1.font", method="anti_cheat", @@ -234,9 +305,11 @@ def test_font_policy_fail(self) -> None: assert len(flags) > 0 def test_no_full_slide_raster_pass(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="picture", bbox=(0, 0, 3000000, 2000000)), # small image - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="picture", bbox=(0, 0, 3000000, 2000000)), # small image + ] + ) item = _make_item("s1.raster", method="anti_cheat", selector="no_full_slide_raster") deck = _make_deck([slide]) @@ -244,9 +317,11 @@ def test_no_full_slide_raster_pass(self) -> None: assert results[0].items[0].passed is True def test_no_full_slide_raster_fail(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="picture", bbox=(0, 0, 12000000, 6800000)), # ~97% of slide - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="picture", bbox=(0, 0, 12000000, 6800000)), # ~97% of slide + ] + ) item = _make_item( "s1.raster", method="anti_cheat", @@ -265,10 +340,12 @@ def test_no_full_slide_raster_fail(self) -> None: class TestZeroSlidePropagation: def test_auto_fail_zeroes_other_items(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[TextRun(text="X", font_family="Arial")]), - SceneObject(obj_type="table", is_table=True, table_rows=2, table_cols=2), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape", text_runs=[TextRun(text="X", font_family="Arial")]), + SceneObject(obj_type="table", is_table=True, table_rows=2, table_cols=2), + ] + ) font_item = _make_item( "s1.font", @@ -295,13 +372,26 @@ def test_auto_fail_zeroes_other_items(self) -> None: class TestScoring: def test_perfect_score(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="table", is_table=True, table_rows=3, table_cols=4), - SceneObject(obj_type="shape", placeholder_type="title"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="table", is_table=True, table_rows=3, table_cols=4), + SceneObject(obj_type="shape", placeholder_type="title"), + ] + ) items = [ - _make_item("s1.table", selector="table", severity="critical", expectation={"exact_count": 1, "required": True}), - _make_item("s1.ph", method="layout_check", selector="placeholder", severity="major", expectation={"placeholder_type": "title", "min_count": 1}), + _make_item( + "s1.table", + selector="table", + severity="critical", + expectation={"exact_count": 1, "required": True}, + ), + _make_item( + "s1.ph", + method="layout_check", + selector="placeholder", + severity="major", + expectation={"placeholder_type": "title", "min_count": 1}, + ), ] deck = _make_deck([slide]) @@ -312,12 +402,21 @@ def test_perfect_score(self) -> None: assert total == 2 def test_partial_score(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), # no table, no placeholder - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), # no table, no placeholder + ] + ) items = [ - _make_item("s1.table", selector="table", severity="critical", expectation={"exact_count": 1, "required": True}), - _make_item("s1.shapes", selector="shape", severity="minor", expectation={"min_count": 1}), + _make_item( + "s1.table", + selector="table", + severity="critical", + expectation={"exact_count": 1, "required": True}, + ), + _make_item( + "s1.shapes", selector="shape", severity="minor", expectation={"min_count": 1} + ), ] deck = _make_deck([slide]) @@ -332,7 +431,9 @@ def test_partial_score(self) -> None: def test_informational_excluded(self) -> None: slide = _make_slide(objects=[]) items = [ - _make_item("s1.info", selector="shape", severity="informational", expectation={"min_count": 1}), + _make_item( + "s1.info", selector="shape", severity="informational", expectation={"min_count": 1} + ), ] deck = _make_deck([slide]) @@ -343,12 +444,18 @@ def test_informational_excluded(self) -> None: assert total == 0 def test_weighted_scoring(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape"), - ]) + slide = _make_slide( + objects=[ + SceneObject(obj_type="shape"), + ] + ) items = [ - _make_item("s1.crit", selector="shape", severity="critical", expectation={"min_count": 1}), - _make_item("s1.fail", selector="table", severity="major", expectation={"required": True}), + _make_item( + "s1.crit", selector="shape", severity="critical", expectation={"min_count": 1} + ), + _make_item( + "s1.fail", selector="table", severity="major", expectation={"required": True} + ), ] deck = _make_deck([slide]) @@ -392,9 +499,13 @@ def test_slide_count_wrong(self) -> None: assert deck_items[0].passed is False def test_deck_font_policy_pass(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[TextRun(text="OK", font_family="Carlito")]), - ]) + slide = _make_slide( + objects=[ + SceneObject( + obj_type="shape", text_runs=[TextRun(text="OK", font_family="Carlito")] + ), + ] + ) deck = _make_deck([slide]) item = _make_item( "deck.font", @@ -408,9 +519,13 @@ def test_deck_font_policy_pass(self) -> None: assert deck_items[0].passed is True def test_deck_font_policy_fail(self) -> None: - slide = _make_slide(objects=[ - SceneObject(obj_type="shape", text_runs=[TextRun(text="Bad", font_family="Courier New")]), - ]) + slide = _make_slide( + objects=[ + SceneObject( + obj_type="shape", text_runs=[TextRun(text="Bad", font_family="Courier New")] + ), + ] + ) deck = _make_deck([slide]) item = _make_item( "deck.font", @@ -430,17 +545,24 @@ def test_tier_scoring(self) -> None: slides = [] items = [] for i in range(1, 21): - slides.append(_make_slide(slide_number=i, objects=[ - SceneObject(obj_type="shape"), - ])) - items.append(_make_item( - f"s{i}.shape", - slide=i, - tier=1 if i <= 5 else (2 if i <= 12 else 3), - selector="shape", - severity="major", - expectation={"min_count": 1}, - )) + slides.append( + _make_slide( + slide_number=i, + objects=[ + SceneObject(obj_type="shape"), + ], + ) + ) + items.append( + _make_item( + f"s{i}.shape", + slide=i, + tier=1 if i <= 5 else (2 if i <= 12 else 3), + selector="shape", + severity="major", + expectation={"min_count": 1}, + ) + ) deck = _make_deck(slides) results, deck_items, _ = evaluate_checklist(deck, items, tier_slides=list(range(1, 21))) @@ -449,6 +571,42 @@ def test_tier_scoring(self) -> None: assert "level_1" in tier_scores assert "level_2" in tier_scores assert "level_3" in tier_scores - assert tier_scores["level_1"]["fidelity_score"] == 1.0 - assert tier_scores["level_2"]["fidelity_score"] == 1.0 - assert tier_scores["level_3"]["fidelity_score"] == 1.0 + level_1 = tier_scores["level_1"] + level_2 = tier_scores["level_2"] + level_3 = tier_scores["level_3"] + assert level_1 is None + assert level_2 is None + assert level_3 is not None and level_3["fidelity_score"] == 1.0 + + +class TestDeckVisualScoring: + def test_all_targeted_slides_must_meet_threshold(self) -> None: + item = _make_item( + "deck.visual", + scope="deck", + slide=None, + method="visual_ssim", + expectation={"min_ssim": 0.99}, + ) + visual = [ + VisualComparisonResult(1, 1.0, True), + VisualComparisonResult(2, 0.98, False), + ] + + _, deck_items, _ = evaluate_checklist(_make_deck(), [item], visual) + + assert deck_items[0].passed is False + assert "1/2 slides" in deck_items[0].details + + def test_missing_visual_results_fail_deck_visual_item(self) -> None: + item = _make_item( + "deck.visual", + scope="deck", + slide=None, + method="visual_ssim", + ) + + _, deck_items, _ = evaluate_checklist(_make_deck(), [item]) + + assert deck_items[0].passed is False + assert "No visual" in deck_items[0].details diff --git a/acidslide-v1/grader/tests/test_export.py b/acidslide-v1/grader/tests/test_export.py new file mode 100644 index 0000000..22641df --- /dev/null +++ b/acidslide-v1/grader/tests/test_export.py @@ -0,0 +1,439 @@ +"""Tests for deterministic slide export helpers and diagnostics.""" + +from __future__ import annotations + +import os +import subprocess +import xml.etree.ElementTree as ET +from decimal import Decimal +from pathlib import Path + +import pytest +from PIL import Image +from pypdf import PdfWriter + +from acidslide import export +from acidslide.models import SlideExport + +_MAC_FONTCONFIG_STDERR = "\n".join( + ( + "Fontconfig warning: no elements found. Check configuration.", + "Fontconfig warning: adding " + "/@.__________________________________________________OOO/var/cache/fontconfig" + "", + 'Fontconfig warning: adding fontconfig', + ) +) + + +def test_normalize_exports_rejects_noncanonical_dimensions( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(export, "EXPORT_WIDTH", 64) + monkeypatch.setattr(export, "EXPORT_HEIGHT", 36) + source = tmp_path / "raw-1.png" + Image.new("RGB", (32, 18), "red").save(source) + + with pytest.raises(RuntimeError, match="expected 64x36"): + export._normalize_exports([source], tmp_path) + + +def test_normalize_exports_uses_stable_names( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(export, "EXPORT_WIDTH", 64) + monkeypatch.setattr(export, "EXPORT_HEIGHT", 36) + source = tmp_path / "raw-1.png" + Image.new("RGB", (64, 36), "red").save(source) + + exports = export._normalize_exports([source], tmp_path) + + assert exports[0].path == tmp_path / "slide-01.png" + assert exports[0].path.name == "slide-01.png" + with Image.open(exports[0].path) as image: + assert image.size == (64, 36) + + +def test_pdf_to_pngs_sorts_pages_numerically( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(export, "EXPORT_WIDTH", 64) + monkeypatch.setattr(export, "EXPORT_HEIGHT", 36) + monkeypatch.setattr("acidslide.export.shutil.which", lambda _name: "/usr/bin/pdftoppm") + + def fake_run(command: list[str], *, check: bool) -> subprocess.CompletedProcess[str]: + assert check is True + prefix = Path(command[-1]) + Image.new("RGB", (64, 36), "red").save(prefix.with_name(f"{prefix.name}-10.png")) + Image.new("RGB", (64, 36), "blue").save(prefix.with_name(f"{prefix.name}-2.png")) + return subprocess.CompletedProcess(command, 0) + + monkeypatch.setattr(export, "_run_conversion", fake_run) + + exports = export._pdf_to_pngs(tmp_path / "slides.pdf", tmp_path) + + assert [item.path.name for item in exports] == ["slide-01.png", "slide-02.png"] + with Image.open(exports[0].path) as first: + assert first.getpixel((0, 0)) == (0, 0, 255) + + +def test_pdf_to_pngs_requires_converter(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr("acidslide.export.shutil.which", lambda _name: None) + + with pytest.raises(RuntimeError, match="poppler-utils"): + export._pdf_to_pngs(tmp_path / "slides.pdf", tmp_path) + + +def test_run_conversion_surfaces_nonzero_exit(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr( + "acidslide.export.subprocess.run", + lambda *_args, **_kwargs: subprocess.CompletedProcess(["renderer"], 7, "", "broken"), + ) + + with pytest.raises(RuntimeError, match="code 7: broken"): + export._run_conversion(["renderer"], check=True) + + +def test_run_conversion_rejects_unclassified_success_stderr( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + "acidslide.export.subprocess.run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + ["libreoffice"], 0, "converted", "unexpected warning" + ), + ) + + with pytest.raises(RuntimeError, match="unclassified stderr"): + export._run_conversion(["libreoffice", "--convert-to", "pdf"], check=True) + + +def test_run_conversion_rejects_exact_mac_fontconfig_warning_bundle( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr( + "acidslide.export.subprocess.run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + ["libreoffice"], 0, "converted", _MAC_FONTCONFIG_STDERR + "\n" + ), + ) + + with pytest.raises(RuntimeError, match="unclassified stderr") as error: + export._run_conversion(["libreoffice", "--convert-to", "pdf"], check=True) + + assert "no elements found" in str(error.value) + assert "/var/cache/fontconfig" in str(error.value) + + +def test_run_conversion_rejects_mac_bundle_with_additional_unknown_warning( + monkeypatch: pytest.MonkeyPatch, +) -> None: + stderr = _MAC_FONTCONFIG_STDERR + "\nunknown fourth warning\n" + monkeypatch.setattr( + "acidslide.export.subprocess.run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + ["libreoffice"], 0, "converted", stderr + ), + ) + + with pytest.raises(RuntimeError, match="unknown fourth warning"): + export._run_conversion(["libreoffice", "--convert-to", "pdf"], check=True) + + +def test_run_conversion_accepts_exact_javaldx_diagnostic( + monkeypatch: pytest.MonkeyPatch, +) -> None: + warning = "Warning: failed to launch javaldx - java may not function correctly" + monkeypatch.setattr( + "acidslide.export.subprocess.run", + lambda *_args, **_kwargs: subprocess.CompletedProcess( + ["libreoffice"], 0, "converted", warning + "\n" + ), + ) + + completed = export._run_conversion(["libreoffice", "--convert-to", "pdf"], check=True) + + assert completed.returncode == 0 + + +def test_find_libreoffice_failure_is_actionable(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr("acidslide.export.shutil.which", lambda _candidate: None) + + with pytest.raises(RuntimeError, match="LibreOffice not found"): + export.find_libreoffice() + + +def test_export_slides_always_uses_pdf_pipeline( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + submission = tmp_path / "submission.pptx" + submission.write_bytes(b"pptx") + destination = tmp_path / "output" + monkeypatch.setattr(export, "find_libreoffice", lambda: Path("/renderer")) + expected = [SlideExport(1, destination / "slide-01.png")] + calls: list[tuple[Path, Path, Path]] = [] + + def fake_pdf( + pptx: Path, + output: Path, + renderer: Path, + *, + expected_page_count: int | None = None, + pdf_output: Path | None = None, + ) -> list[SlideExport]: + assert expected_page_count is None + assert pdf_output is None + calls.append((pptx, output, renderer)) + return expected + + monkeypatch.setattr(export, "_export_via_pdf", fake_pdf) + + assert export.export_slides(submission, destination) == expected + assert len(calls) == 1 + assert calls[0][1:] == (destination, Path("/renderer")) + + +def test_export_via_pdf_requires_generated_pdf( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr( + export, + "_run_conversion", + lambda _command, *, check, env=None: subprocess.CompletedProcess(["renderer"], 0), + ) + + with pytest.raises(RuntimeError, match="failed to produce PDF"): + export._export_via_pdf(tmp_path / "submission.pptx", tmp_path, Path("/renderer")) + + +def test_export_via_pdf_retains_validated_pdf( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + source = tmp_path / "submission.pptx" + source.write_bytes(b"pptx") + retained = tmp_path / "evidence" / "canonical.pdf" + + def fake_run( + command: list[str], + *, + check: bool, + env: dict[str, str] | None = None, + ) -> subprocess.CompletedProcess[str]: + assert check is True + assert env is not None + if "--convert-to" in command: + profile_arguments = [ + value for value in command if value.startswith("-env:UserInstallation=") + ] + assert len(profile_arguments) == 1 + assert profile_arguments[0].startswith("-env:UserInstallation=file://") + assert profile_arguments[0] != ( + "-env:UserInstallation=file://" + ) + output = Path(command[command.index("--outdir") + 1]) / "submission.pdf" + output.write_bytes(b"canonical-pdf") + return subprocess.CompletedProcess(command, 0) + + monkeypatch.setattr(export, "_run_conversion", fake_run) + monkeypatch.setattr(export, "_pdf_to_pngs", lambda *_args, **_kwargs: []) + + assert ( + export._export_via_pdf( + source, + tmp_path / "exports", + Path("/renderer"), + pdf_output=retained, + ) + == [] + ) + assert retained.read_bytes() == b"canonical-pdf" + + +def test_local_export_generates_isolated_fontconfig_for_libreoffice_only( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + benchmark = tmp_path / "benchmark" + fonts = benchmark / "fonts" / "files" + fonts.mkdir(parents=True) + (fonts / "Test & Demo.ttf").write_bytes(b"font") + source = tmp_path / "submission.pptx" + source.write_bytes(b"pptx") + sentinel = "preserved-value" + monkeypatch.delenv("FONTCONFIG_FILE", raising=False) + monkeypatch.delenv("FONTCONFIG_PATH", raising=False) + monkeypatch.setenv("ACIDSLIDE_EXPORT_TEST_SENTINEL", sentinel) + monkeypatch.setattr(export, "resolve_benchmark_dir", lambda: benchmark) + observed_environment: dict[str, str] | None = None + + def fake_run( + command: list[str], + *, + check: bool, + env: dict[str, str] | None = None, + ) -> subprocess.CompletedProcess[str]: + nonlocal observed_environment + assert check is True + assert env is not None + observed_environment = env + assert env["ACIDSLIDE_EXPORT_TEST_SENTINEL"] == sentinel + config_path = Path(env["FONTCONFIG_FILE"]) + assert Path(env["FONTCONFIG_PATH"]) == config_path.parent + root = ET.parse(config_path).getroot() + assert root.tag == "fontconfig" + assert [node.text for node in root.findall("dir")] == [str(fonts.resolve())] + caches = root.findall("cachedir") + assert len(caches) == 1 + assert caches[0].text is not None + cache_path = Path(caches[0].text) + assert cache_path.is_dir() + assert cache_path.parent == config_path.parent + output = Path(command[command.index("--outdir") + 1]) / "submission.pdf" + output.write_bytes(b"local-pdf") + return subprocess.CompletedProcess(command, 0) + + monkeypatch.setattr(export, "_run_conversion", fake_run) + monkeypatch.setattr(export, "_pdf_to_pngs", lambda *_args, **_kwargs: []) + + assert export._export_via_pdf(source, tmp_path / "exports", Path("/renderer")) == [] + assert observed_environment is not None + assert "FONTCONFIG_FILE" not in os.environ + assert "FONTCONFIG_PATH" not in os.environ + + +def test_existing_frozen_fontconfig_environment_is_preserved_exactly( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + source = tmp_path / "submission.pptx" + source.write_bytes(b"pptx") + frozen_file = "/opt/acidslide/fontconfig/fonts.conf" + frozen_path = "/opt/acidslide/fontconfig" + monkeypatch.setenv("FONTCONFIG_FILE", frozen_file) + monkeypatch.setenv("FONTCONFIG_PATH", frozen_path) + monkeypatch.setattr( + export, + "resolve_benchmark_dir", + lambda: pytest.fail("frozen environment must not generate host Fontconfig"), + ) + expected_environment = dict(os.environ) + observed_environment: dict[str, str] | None = None + + def fake_run( + command: list[str], + *, + check: bool, + env: dict[str, str] | None = None, + ) -> subprocess.CompletedProcess[str]: + nonlocal observed_environment + assert check is True + assert env is not None + observed_environment = env + output = Path(command[command.index("--outdir") + 1]) / "submission.pdf" + output.write_bytes(b"canonical-pdf") + return subprocess.CompletedProcess(command, 0) + + monkeypatch.setattr(export, "_run_conversion", fake_run) + monkeypatch.setattr(export, "_pdf_to_pngs", lambda *_args, **_kwargs: []) + + assert export._export_via_pdf(source, tmp_path / "exports", Path("/renderer")) == [] + assert observed_environment == expected_environment + assert observed_environment["FONTCONFIG_FILE"] == frozen_file + assert observed_environment["FONTCONFIG_PATH"] == frozen_path + + +def test_missing_benchmark_fonts_fail_before_renderer( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + benchmark = tmp_path / "benchmark" + benchmark.mkdir() + monkeypatch.delenv("FONTCONFIG_FILE", raising=False) + monkeypatch.delenv("FONTCONFIG_PATH", raising=False) + monkeypatch.setattr(export, "resolve_benchmark_dir", lambda: benchmark) + monkeypatch.setattr( + export, + "_run_conversion", + lambda *_args, **_kwargs: pytest.fail("renderer must not run without benchmark fonts"), + ) + + with pytest.raises(RuntimeError, match="Bundled benchmark fonts are unavailable"): + export._export_via_pdf( + tmp_path / "submission.pptx", + tmp_path / "exports", + Path("/renderer"), + ) + + +def test_run_conversion_surfaces_timeout(monkeypatch: pytest.MonkeyPatch) -> None: + def timeout(*_args: object, **_kwargs: object) -> None: + raise subprocess.TimeoutExpired("renderer", export.EXPORT_TIMEOUT) + + monkeypatch.setattr("acidslide.export.subprocess.run", timeout) + + with pytest.raises(RuntimeError, match="timed out"): + export._run_conversion(["renderer"], check=True) + + +def _write_exact_minimal_pdf(path: Path) -> None: + objects = [ + b"<< /Type /Catalog /Pages 2 0 R >>", + b"<< /Type /Pages /Kids [3 0 R 4 0 R] /Count 2 >>", + b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 960.009448818898 540] >>", + b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 960.009448818898 540] " + b"/CropBox [0 0 960.009448818898 540] >>", + ] + payload = bytearray(b"%PDF-1.4\n") + offsets = [0] + for object_number, body in enumerate(objects, 1): + offsets.append(len(payload)) + payload.extend(f"{object_number} 0 obj\n".encode()) + payload.extend(body + b"\nendobj\n") + xref_offset = len(payload) + payload.extend(f"xref\n0 {len(offsets)}\n".encode()) + payload.extend(b"0000000000 65535 f \n") + for offset in offsets[1:]: + payload.extend(f"{offset:010d} 00000 n \n".encode()) + payload.extend( + f"trailer\n<< /Size {len(offsets)} /Root 1 0 R >>\n" + f"startxref\n{xref_offset}\n%%EOF\n".encode() + ) + path.write_bytes(payload) + + +def test_pdf_geometry_accepts_exact_v1_pages(tmp_path: Path) -> None: + pdf = tmp_path / "slides.pdf" + _write_exact_minimal_pdf(pdf) + + export._validate_pdf_geometry(pdf, 2) + + +@pytest.mark.parametrize( + ("pages", "width", "rotation", "message"), + [ + (1, export.PDF_WIDTH_POINTS, 0, "contains 1 pages"), + (2, export.PDF_WIDTH_POINTS, 90, "rotation 90"), + (2, Decimal("960"), 0, "MediaBox/effective CropBox"), + ], +) +def test_pdf_geometry_fails_closed( + tmp_path: Path, + pages: int, + width: Decimal, + rotation: int, + message: str, +) -> None: + pdf = tmp_path / "slides.pdf" + writer = PdfWriter() + for page_number in range(pages): + page = writer.add_blank_page( + width=float(width), + height=float(export.PDF_HEIGHT_POINTS), + ) + if page_number == 0 and rotation: + page.rotate(rotation) + writer.write(pdf) + + with pytest.raises(RuntimeError, match=message): + export._validate_pdf_geometry(pdf, 2) + + +def test_page_number_handles_invalid_name() -> None: + assert export._page_number(Path("slide-nope.png")) == 0 diff --git a/acidslide-v1/grader/tests/test_export_determinism_evidence.py b/acidslide-v1/grader/tests/test_export_determinism_evidence.py new file mode 100644 index 0000000..4e8214c --- /dev/null +++ b/acidslide-v1/grader/tests/test_export_determinism_evidence.py @@ -0,0 +1,192 @@ +"""Tests for the normative 100-run export-determinism evidence contract.""" + +from __future__ import annotations + +import copy +import hashlib +import json +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any, cast + +import jsonschema + +from acidslide.release_evidence import validate_export_determinism_evidence + +SCHEMA_PATH = ( + Path(__file__).resolve().parents[2] / "schemas" / "export-determinism-evidence.schema.json" +) + + +@dataclass +class _Result: + errors: list[str] = field(default_factory=list) + notes: list[str] = field(default_factory=list) + + def require(self, condition: bool, message: str) -> None: + if not condition: + self.errors.append(message) + + +def _hash(label: str) -> str: + return f"sha256:{hashlib.sha256(label.encode()).hexdigest()}" + + +def _evidence() -> tuple[dict[str, Any], dict[str, Any]]: + canonical_pngs = [_hash(f"canonical-page-{page}") for page in range(1, 21)] + bindings: dict[str, Any] = { + "environment_attestation_sha256": _hash("environment"), + "original_gold_sha256": _hash("original-gold"), + "resolved_gold_sha256": _hash("resolved-gold"), + "canonical_package_hash_profile_sha256": _hash("package-profile"), + "canonical_package_hash_v1": _hash("canonical-package"), + "canonical_pdf_sha256": _hash("canonical-pdf"), + "canonical_png_sha256s": canonical_pngs, + "export_profile_sha256": _hash("export-profile"), + "ssim_profile_sha256": _hash("ssim-profile"), + } + runs = [] + for run in range(1, 101): + runs.append( + { + "run": run, + "pdf_sha256": ( + bindings["canonical_pdf_sha256"] if run == 1 else _hash(f"pdf-{run}") + ), + "export_bundle_sha256": _hash(f"export-bundle-{run}"), + "pages": [ + { + "page": page, + "png_sha256": ( + canonical_pngs[page - 1] + if run == 1 + else _hash(f"run-{run}-page-{page}") + ), + } + for page in range(1, 21) + ], + } + ) + run_pairs = [ + { + "run_a": run_a, + "run_b": run_b, + "page_comparisons": [{"page": page, "ssim": 1.0} for page in range(1, 21)], + "minimum_ssim": 1.0, + } + for run_a in range(1, 101) + for run_b in range(run_a + 1, 101) + ] + return ( + { + "schema_version": "1.0", + "evidence_id": "acidslide-export-determinism-evidence-v1", + "benchmark_version": "acidslide-v1.0.0", + "canonicalization": "RFC8785-JCS", + "measured_at": "2026-07-18T00:00:00Z", + "bindings": copy.deepcopy(bindings), + "run_count": 100, + "page_count": 20, + "run_pair_count": 4950, + "page_pair_comparison_count": 99000, + "required_minimum_ssim": 0.99999, + "canonical_run": 1, + "runs": runs, + "run_pairs": run_pairs, + "minimum_ssim_by_page": [{"page": page, "minimum_ssim": 1.0} for page in range(1, 21)], + "global_minimum_ssim": 1.0, + }, + bindings, + ) + + +BASE_EVIDENCE, EXPECTED_BINDINGS = _evidence() + + +def _schema_validator() -> jsonschema.Draft202012Validator: + schema = cast("dict[str, Any]", json.loads(SCHEMA_PATH.read_text(encoding="utf-8"))) + jsonschema.Draft202012Validator.check_schema(schema) + return jsonschema.Draft202012Validator( + schema, + format_checker=jsonschema.FormatChecker(), + ) + + +def test_complete_100_run_matrix_validates_and_recomputes() -> None: + evidence = copy.deepcopy(BASE_EVIDENCE) + _schema_validator().validate(evidence) + result = _Result() + + validate_export_determinism_evidence( + result, + evidence, + expected_bindings=EXPECTED_BINDINGS, + ) + + assert result.errors == [] + assert len(cast("list[Any]", evidence["runs"])) == 100 + assert len(cast("list[Any]", evidence["run_pairs"])) == 4950 + assert ( + sum( + len(cast("list[Any]", pair["page_comparisons"])) + for pair in cast("list[dict[str, Any]]", evidence["run_pairs"]) + ) + == 99000 + ) + + +def test_environment_gold_or_score_tampering_fails_closed() -> None: + evidence = copy.deepcopy(BASE_EVIDENCE) + bindings = cast("dict[str, Any]", evidence["bindings"]) + bindings["resolved_gold_sha256"] = _hash("substituted-gold") + first_pair = cast("list[dict[str, Any]]", evidence["run_pairs"])[0] + cast("list[dict[str, Any]]", first_pair["page_comparisons"])[0]["ssim"] = 0.999995 + result = _Result() + + validate_export_determinism_evidence( + result, + evidence, + expected_bindings=EXPECTED_BINDINGS, + ) + + assert any("wrong environment or gold identity" in error for error in result.errors) + assert any("run-pair minimum" in error for error in result.errors) + assert any("per-page minimum" in error for error in result.errors) + + +def test_missing_run_pair_and_page_comparisons_fail_exact_counts() -> None: + evidence = copy.deepcopy(BASE_EVIDENCE) + cast("list[Any]", evidence["run_pairs"]).pop() + evidence["page_pair_comparison_count"] = 98980 + schema_errors = list(_schema_validator().iter_errors(evidence)) + result = _Result() + + validate_export_determinism_evidence( + result, + evidence, + expected_bindings=EXPECTED_BINDINGS, + ) + + assert schema_errors + assert any("wrong run/comparison counts" in error for error in result.errors) + assert any("100-choose-2" in error for error in result.errors) + assert any("99,000" in error for error in result.errors) + + +def test_recomputed_minimum_below_099999_fails_threshold() -> None: + evidence = copy.deepcopy(BASE_EVIDENCE) + first_pair = cast("list[dict[str, Any]]", evidence["run_pairs"])[0] + cast("list[dict[str, Any]]", first_pair["page_comparisons"])[0]["ssim"] = 0.99998 + first_pair["minimum_ssim"] = 0.99998 + page_minima = cast("list[dict[str, Any]]", evidence["minimum_ssim_by_page"]) + page_minima[0]["minimum_ssim"] = 0.99998 + evidence["global_minimum_ssim"] = 0.99998 + result = _Result() + + validate_export_determinism_evidence( + result, + evidence, + expected_bindings=EXPECTED_BINDINGS, + ) + + assert result.errors == ["export determinism per-page or global minimum SSIM is below 0.99999"] diff --git a/acidslide-v1/grader/tests/test_integration.py b/acidslide-v1/grader/tests/test_integration.py index f675028..91c91e5 100644 --- a/acidslide-v1/grader/tests/test_integration.py +++ b/acidslide-v1/grader/tests/test_integration.py @@ -1,4 +1,4 @@ -"""Integration tests — run the full pipeline against AcidSlide_v1.pptx.""" +"""Integration tests against the promoted canonical AcidSlide v1 gold deck.""" from __future__ import annotations @@ -8,14 +8,14 @@ from acidslide.checklist import load_checklist from acidslide.evaluate import compute_fidelity_score, evaluate_checklist -from acidslide.inspect_ooxml import extract_deck_graph +from acidslide.inspect_ooxml import SceneObject, extract_deck_graph -PPTX_PATH = Path(__file__).resolve().parents[2] / "AcidSlide_v1.pptx" BENCHMARK_DIR = Path(__file__).resolve().parents[2] / "benchmark" +PPTX_PATH = BENCHMARK_DIR / "deck" / "gold" / "acidslide-v1-gold.pptx" pytestmark = pytest.mark.skipif( not PPTX_PATH.exists(), - reason="AcidSlide_v1.pptx not found", + reason="canonical AcidSlide v1 gold deck not found", ) @@ -144,7 +144,7 @@ def test_grade_report_structure(self) -> None: assert isinstance(flags, list) # Print summary for inspection - print(f"\n--- AcidSlide v1 Grade Summary ---") + print("\n--- AcidSlide v1 Grade Summary ---") print(f"Fidelity: {fidelity:.4f}") print(f"Passed: {passed}/{total}") print(f"Anti-cheat flags: {len(flags)}") @@ -157,9 +157,9 @@ def test_grade_report_structure(self) -> None: print(f" Deck {di.id}: {status} — {di.details}") -def _flatten(obj) -> list: +def _flatten(obj: SceneObject) -> list[SceneObject]: """Flatten object children recursively.""" - result = [] + result: list[SceneObject] = [] for child in obj.children: result.append(child) result.extend(_flatten(child)) diff --git a/acidslide-v1/grader/tests/test_mce.py b/acidslide-v1/grader/tests/test_mce.py new file mode 100644 index 0000000..90c121d --- /dev/null +++ b/acidslide-v1/grader/tests/test_mce.py @@ -0,0 +1,137 @@ +"""Tests for ECMA-376 Markup Compatibility preprocessing.""" + +from __future__ import annotations + +import zipfile +from typing import TYPE_CHECKING + +import pytest +from lxml import etree + +from acidslide.inspect_ooxml import extract_deck_graph +from acidslide.mce import MC_NAMESPACE, MCEProfileError, preprocess_markup_compatibility + +if TYPE_CHECKING: + from pathlib import Path + +PRESENTATION_NS = "http://schemas.openxmlformats.org/presentationml/2006/main" +P14_NS = "http://schemas.microsoft.com/office/powerpoint/2010/main" + + +def _document() -> etree._Element: + return etree.fromstring( + f""" + + + + + """ + ) + + +def test_unsupported_choice_uses_fallback() -> None: + root = preprocess_markup_compatibility(_document(), {PRESENTATION_NS}) + + transition = root[0] + assert etree.QName(transition).localname == "transition" + assert transition.get("spd") == "slow" + assert transition.get(f"{{{P14_NS}}}dur") is None + + +def test_understood_choice_is_selected() -> None: + root = preprocess_markup_compatibility(_document(), {PRESENTATION_NS, P14_NS}) + + transition = root[0] + assert transition.get(f"{{{P14_NS}}}dur") == "2000" + assert transition.get("spd") is None + + +def test_unsupported_choice_without_fallback_fails_closed() -> None: + root = etree.fromstring( + f""" + + + + """ + ) + + with pytest.raises(MCEProfileError, match="neither a supported"): + preprocess_markup_compatibility(root, {PRESENTATION_NS}) + + +def test_undeclared_prefix_and_must_understand_fail_closed() -> None: + undeclared = etree.fromstring( + f'' + ) + with pytest.raises(MCEProfileError, match="Undeclared"): + preprocess_markup_compatibility(undeclared, {PRESENTATION_NS}) + + must_understand = etree.fromstring( + f'' + ) + with pytest.raises(MCEProfileError, match="MustUnderstand"): + preprocess_markup_compatibility(must_understand, {PRESENTATION_NS}) + + +def test_process_content_splices_children_and_preserve_records_evidence() -> None: + extension = "urn:acidslide:unsupported" + root = etree.fromstring( + f''' + + + ''' + ) + evidence: list[dict[str, str]] = [] + + preprocess_markup_compatibility( + root, + {PRESENTATION_NS}, + preserved_evidence=evidence, + ) + + assert len(root) == 1 + assert root[0].get("spd") == "slow" + assert evidence[0]["kind"] == "element" + assert evidence[0]["qname"] == f"{{{extension}}}preserved" + + +def test_scene_graph_extraction_processes_alternate_content(tmp_path: Path) -> None: + pptx = tmp_path / "mce.pptx" + with zipfile.ZipFile(pptx, "w") as archive: + archive.writestr( + "ppt/presentation.xml", + f""" + + """, + ) + archive.writestr( + "ppt/_rels/presentation.xml.rels", + """ + + """, + ) + archive.writestr( + "ppt/slides/slide1.xml", + f""" + + + + + + + + """, + ) + + deck = extract_deck_graph(pptx) + + assert len(deck.slides) == 1 + assert len(deck.slides[0].objects) == 1 + assert deck.slides[0].objects[0].name == "fallback" diff --git a/acidslide-v1/grader/tests/test_models.py b/acidslide-v1/grader/tests/test_models.py new file mode 100644 index 0000000..0e7638d --- /dev/null +++ b/acidslide-v1/grader/tests/test_models.py @@ -0,0 +1,298 @@ +"""Tests for machine-readable and human-readable grade reports.""" + +from __future__ import annotations + +import hashlib +import json +from dataclasses import replace +from pathlib import Path +from typing import Any + +import jsonschema +import rfc8785 + +from acidslide.models import ( + DisqualificationState, + GoldDuplicateCheck, + GradeReport, + GradingMode, + RunKind, + StableError, +) + +SHA = {index: f"sha256:{str(index) * 64}" for index in range(10)} + + +def _environment_attestation() -> dict[str, Any]: + versions = { + name: "test-1.0" + for name in ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + ) + } + return { + "schema_version": "1.0", + "attestation_id": "acidslide-environment-attestation-v1", + "canonicalization": "RFC8785-JCS", + "attestation_state": "verified", + "attested_at": "2026-07-18T12:00:00Z", + "platform": "linux/amd64", + "oci_image_digest": SHA[1], + "build_inputs": { + "dockerfile_sha256": SHA[2], + "grader_lockfile_sha256": SHA[3], + "base_image_digest": SHA[4], + "uv_image_digest": SHA[5], + }, + "runtime_versions": versions, + "binary_inventory": [ + {"name": name, "path": f"/usr/bin/{name}", "sha256": SHA[index]} + for index, name in enumerate( + ("libreoffice", "pdftoppm", "python", "fontconfig", "libfaketime"), start=2 + ) + ], + "font_environment": { + "fontconfig_file": "/etc/fonts/fonts.conf", + "fontconfig_config_sha256": SHA[6], + "font_manifest_sha256": SHA[7], + "discovered_fonts": [{"path": "/fonts/Test.ttf", "sha256": SHA[8]}], + "exact_manifest_match": True, + }, + "process_environment": { + "FAKETIME": "@2025-01-01 00:00:00", + "FAKETIME_DONT_FAKE_MONOTONIC": "1", + "FAKETIME_NO_CACHE": "1", + "LD_PRELOAD": "/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1", + "TZ": "UTC", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US.UTF-8", + }, + "export_contract": { + "libreoffice_command": [ + "libreoffice", + "--headless", + "-env:UserInstallation=file://", + "--convert-to", + "pdf", + "--outdir", + "/work", + "/input/submission.pptx", + ], + "pdftoppm_command": [ + "pdftoppm", + "-png", + "-scale-to-x", + "1920", + "-scale-to-y", + "1080", + "/work/submission.pdf", + "/work/acidslide-render", + ], + "presentation_size_emu": {"cx": 12192000, "cy": 6858000}, + "allowed_page_counts": [5, 12, 20], + "width_px": 1920, + "height_px": 1080, + "color_mode": "RGB", + "reference_datetime": "2025-01-01T00:00:00Z", + "pdf_page_geometry": { + "numeric_parser": "exact-decimal-string", + "media_box": ["0", "0", "960.009448818898", "540"], + "crop_box": "absent-or-exactly-equal-to-media-box", + "rotate": "absent-or-zero", + }, + }, + "profile_hashes": { + "export_profile_sha256": SHA[1], + "png_profile_sha256": SHA[2], + "ssim_profile_sha256": SHA[3], + "json_schema_bundle_sha256": SHA[4], + "xsd_bundle_sha256": SHA[5], + "schema_root_map_sha256": SHA[6], + "mce_profile_sha256": SHA[7], + "scene_graph_profile_sha256": SHA[9], + "canonical_package_hash_profile_sha256": SHA[8], + }, + "grader_source_tree_sha256": SHA[2], + "canary": { + "canary_id": "grader-test-canary", + "input_sha256": SHA[8], + "score_semantic_report_sha256": SHA[9], + }, + "verification": { + "architecture_verified": True, + "binary_hashes_verified": True, + "font_inventory_verified": True, + "clock_fixture_verified": True, + "network_disabled_verified": True, + }, + } + + +def _report() -> GradeReport: + environment_attestation = _environment_attestation() + environment_hash = ( + f"sha256:{hashlib.sha256(rfc8785.dumps(environment_attestation)).hexdigest()}" + ) + return GradeReport( + benchmark_version="acidslide-v1.0.0", + grader_version="1.0.0a1", + scoring_cohort_id=SHA[0], + scoring_manifest_sha256=SHA[1], + grader_source_tree_sha256=SHA[2], + environment_attestation_sha256=environment_hash, + grader_package_sha256=SHA[4], + oci_image_digest=SHA[1], + prompt_bundle_sha256=SHA[5], + scored_assertion_inventory_sha256=SHA[6], + checklist_bundle_sha256=SHA[7], + schema_bundle_sha256=SHA[8], + schema_root_map_sha256=SHA[6], + mce_profile_sha256=SHA[7], + asset_manifest_sha256=SHA[8], + font_manifest_sha256=SHA[7], + grading_mode=GradingMode.HOSTED, + run_kind=RunKind.SUBMISSION, + canonical_package_hash_profile_sha256=SHA[8], + canonical_package_hash_v1=SHA[9], + gold_duplicate_check=GoldDuplicateCheck.CLEAR, + generation_seed=None, + submission_id="00000000-0000-4000-8000-000000000001", + campaign_id="00000000-0000-4000-8000-000000000002", + campaign_slot=1, + robustness_group_id=None, + submitter_id="00000000-0000-4000-8000-000000000003", + model_key="00000000-0000-4000-8000-000000000004", + model_revision_key="00000000-0000-4000-8000-000000000005", + targeted_tier=1, + prompt_variant="canonical", + assistance_class="unassisted", + generation_profile_sha256=SHA[4], + submission_sha256=SHA[5], + mce_resolved_package_sha256=SHA[6], + gold_submission_sha256=SHA[7], + gold_mce_resolved_package_sha256=SHA[8], + gold_canonical_package_hash_v1=SHA[9], + schema_valid=False, + schema_validation_performed=True, + visual_verification_performed=False, + verification_complete=False, + scoring_completed=False, + disqualification_state=DisqualificationState.COMPLETED_INELIGIBLE, + ineligibility_reasons=["schema_validation_failed", "verification_incomplete"], + repair_triggered=False, + grading_duration_seconds=0.0, + fidelity_score=None, + campaign_contribution=0.0, + passed_items=0, + total_items=0, + deck_passed=False, + eligible=False, + tier_scores={"level_1": None, "level_2": None, "level_3": None}, + schema_violations=[ + StableError( + "schema_violation", + part="ppt/slides/slide1.xml", + details="element ", + ) + ], + verification_errors=[ + StableError("schema_validation_failed", details='') + ], + environment_attestation=environment_attestation, + verified_metrics={ + "submission_file_size_bytes": 123, + "grading_duration_seconds": 0.0, + "schema_valid": False, + "schema_validation_performed": True, + "visual_verification_performed": False, + "verification_complete": False, + "renderer_version": "unavailable", + }, + attested_metrics={"generation_strategy": "direct"}, + attestation={ + "method": "artifact-upload", + "human_intervention": False, + "post_processing": False, + "external_resources_used": False, + }, + ) + + +def _schema(name: str) -> dict[str, Any]: + path = Path(__file__).resolve().parents[2] / "schemas" / name + schema: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) + return schema + + +def test_json_contains_verification_provenance() -> None: + payload = json.loads(_report().to_json()) + + assert payload["run_kind"] == "submission" + assert payload["grading_mode"] == "hosted" + assert payload["verification_scope"] == "artifact_conformance" + assert payload["verification_label"] == ("grading-verified artifact score; generation-attested") + assert payload["schema_validation_performed"] is True + assert payload["visual_verification_performed"] is False + assert payload["verification_complete"] is False + assert payload["verification_errors"][0]["code"] == "schema_validation_failed" + + +def test_json_conforms_to_normative_report_schema() -> None: + payload = json.loads(_report().to_json()) + schema = _schema("report.schema.json") + schema["properties"]["environment_attestation"] = _schema("environment-attestation.schema.json") + + jsonschema.Draft202012Validator(schema).validate(payload) + + +def test_semantic_projection_conforms_and_hashes_jcs_bytes() -> None: + report = _report() + projection = report.semantic_projection() + + jsonschema.Draft202012Validator(_schema("report-semantic-projection.schema.json")).validate( + projection + ) + expected = f"sha256:{hashlib.sha256(rfc8785.dumps(projection)).hexdigest()}" + assert report.score_semantic_report_sha256 == expected + + +def test_semantic_projection_excludes_diagnostic_details_but_not_outcomes() -> None: + report = _report() + changed_details = replace( + report, + grading_duration_seconds=9.5, + verification_errors=[ + StableError("schema_validation_failed", details="different private diagnostic") + ], + ) + changed_outcome = replace( + report, + verification_errors=[StableError("artifact_renderer_failure")], + ) + + assert changed_details.score_semantic_report_sha256 == report.score_semantic_report_sha256 + assert changed_outcome.score_semantic_report_sha256 != report.score_semantic_report_sha256 + + +def test_html_escapes_untrusted_report_content() -> None: + rendered = _report().to_html() + + assert " + + + + + +
    +
    +
    +

    Generative Layout & OOXML Scoring System

    +

    Can your model make PowerPoint—or only pictures of it?

    +

    Twenty adversarial slides. Native tables, live charts, multilingual type, masters, groups, fields, and unforgiving geometry. Every published result is labeled exactly: grading-verified artifact score; generation-attested.

    + +
    +
    + +

    Gloss measurement stack

    +
      +
    1. 01Quarantine
    2. +
    3. 02LibreOffice render
    4. +
    5. 03OOXML inspection
    6. +
    7. 04Weighted checklist
    8. +
    +

    No screenshots. No traces. One final .pptx.

    +
    +
    + +
    +
    +
    +

    Current field

    +

    The fidelity board

    +
    +
    Loading verified runs…
    +
    + +
    +
    + + +
    + +
    + +

    +
    Reading the latest verified runs…
    + + + +
    + +
    +
    +

    What the number means

    +

    A score with receipts.

    +

    The service stores an append-only run record and computes the official result from exactly three precommitted campaign slots. Scores are comparable only when the scoring-manifest, grader-source-tree, environment-attestation, and recomputed cohort hashes all match.

    +
    +
    +
    Level 1
    5 foundation slides
    +
    Level 2
    12 intermediate slides
    +
    Level 3
    20 torture slides
    +
    Perfect
    1.0000 weighted fidelity
    +
    +
    + +
    +
    +

    Enter the field

    +

    Bring the final deck.

    +

    Organizations receive an API key from a benchmark maintainer, register immutable model and revision keys, then precommit a campaign. Each upload carries only its campaign_id plus generation attestation; tier, variant, benchmark, and cohort cannot be overridden.

    +
    +
    +
    POST /v1/submissions
    +
    curl https://your-gloss-host/v1/submissions \
    +  -H "Authorization: Bearer $ACIDSLIDE_API_KEY" \
    +  -F 'metadata=@submission.json;type=application/json' \
    +  -F 'file=@model-output.pptx'
    + Open interactive API docs +
    +
    +
    + + + + diff --git a/acidslide-v1/service/acidslide_service/static/site.css b/acidslide-v1/service/acidslide_service/static/site.css new file mode 100644 index 0000000..8f9e39f --- /dev/null +++ b/acidslide-v1/service/acidslide_service/static/site.css @@ -0,0 +1,151 @@ +:root { + --ink: #10262d; + --deep: #0b3c49; + --cyan: #1d697d; + --frost: #f2f7f7; + --paper: #fbfdfc; + --aluminum: #a8b8b8; + --rule: #c9d5d4; + --signal: #ef6045; + --signal-dark: #b53a28; + --success: #167153; + --display: "Arial Narrow", "Avenir Next Condensed", "Helvetica Neue", sans-serif; + --body: Georgia, "Times New Roman", serif; + --utility: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; +} + +* { box-sizing: border-box; } +html { scroll-behavior: smooth; } +body { margin: 0; background: var(--paper); color: var(--ink); font-family: var(--body); } +a { color: inherit; } +button, input { font: inherit; } +code, pre { font-family: var(--utility); } + +.skip-link { position: fixed; top: .75rem; left: .75rem; z-index: 10; transform: translateY(-200%); padding: .75rem 1rem; background: var(--ink); color: white; font-family: var(--utility); } +.skip-link:focus { transform: none; } +:focus-visible { outline: 3px solid var(--signal); outline-offset: 3px; } +.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } + +.site-header { min-height: 5rem; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 2rem; padding: 0 clamp(1.25rem, 4vw, 4.5rem); border-bottom: 1px solid var(--rule); font-family: var(--utility); font-size: .74rem; letter-spacing: .06em; text-transform: uppercase; } +.wordmark { display: inline-flex; width: max-content; align-items: center; gap: .65rem; font: 800 1.3rem/1 var(--display); letter-spacing: -.025em; text-decoration: none; text-transform: none; } +.wordmark svg { width: 1.75rem; height: 1.75rem; fill: none; stroke: var(--signal); stroke-width: 1.7; } +.site-header nav { display: flex; gap: 2rem; } +.site-header nav a, footer nav a { text-decoration: none; border-bottom: 1px solid transparent; } +.site-header nav a:hover, footer nav a:hover { border-bottom-color: currentColor; } +.release-mark { justify-self: end; color: var(--cyan); } + +.hero { min-height: 42rem; display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(19rem, .55fr); border-bottom: 1px solid var(--rule); background-image: linear-gradient(rgba(16,38,45,.055) 1px, transparent 1px), linear-gradient(90deg, rgba(16,38,45,.055) 1px, transparent 1px); background-size: 32px 32px; } +.hero-copy { display: flex; flex-direction: column; justify-content: center; padding: clamp(4rem, 9vw, 9rem) clamp(1.5rem, 7vw, 7.5rem); background: linear-gradient(90deg, rgba(251,253,252,.96), rgba(251,253,252,.79)); } +.eyebrow { margin: 0 0 1.25rem; color: var(--cyan); font: 700 .74rem/1.3 var(--utility); letter-spacing: .12em; text-transform: uppercase; } +h1, h2 { margin: 0; font-family: var(--display); font-weight: 800; letter-spacing: -.045em; } +h1 { max-width: 14ch; font-size: clamp(3.6rem, 7.8vw, 8rem); line-height: .88; text-transform: uppercase; } +h1 em { color: var(--signal); font-style: normal; } +h2 { font-size: clamp(2.8rem, 5vw, 5.5rem); line-height: .92; text-transform: uppercase; } +.lede { max-width: 47rem; margin: 2rem 0 0; font-size: clamp(1.1rem, 1.5vw, 1.35rem); line-height: 1.55; } +.hero-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 1.5rem; margin-top: 2.5rem; } +.primary-action { display: inline-flex; min-height: 3.4rem; align-items: center; padding: 0 1.3rem; background: var(--ink); color: white; font: 700 .78rem var(--utility); letter-spacing: .06em; text-decoration: none; text-transform: uppercase; transition: background .18s, transform .18s; } +.primary-action:hover { background: var(--signal-dark); transform: translateY(-2px); } +.text-action { font: 700 .8rem var(--utility); text-underline-offset: .3rem; } + +.calibration-card { position: relative; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; padding: 2rem; background: var(--deep); color: white; } +.reticle { position: absolute; top: 50%; left: 50%; width: min(20vw, 18rem); aspect-ratio: 1; transform: translate(-50%, -65%); border: 1px solid rgba(255,255,255,.36); border-radius: 50%; } +.reticle::before, .reticle::after, .reticle span::before, .reticle span::after { position: absolute; content: ""; background: rgba(255,255,255,.42); } +.reticle::before { top: 50%; left: -40%; width: 180%; height: 1px; } +.reticle::after { top: -40%; left: 50%; width: 1px; height: 180%; } +.reticle span::before { inset: 24%; border: 1px solid var(--signal); border-radius: 50%; background: transparent; } +.reticle span::after { top: 50%; left: 50%; width: .55rem; height: .55rem; transform: translate(-50%,-50%); border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 .5rem rgba(239,96,69,.16); } +.calibration-label { margin: 0 0 1rem; color: #bcd6da; font: .68rem var(--utility); letter-spacing: .12em; text-transform: uppercase; } +.calibration-card ol { position: relative; z-index: 1; margin: 0; padding: 0; list-style: none; border-top: 1px solid rgba(255,255,255,.28); } +.calibration-card li { display: grid; grid-template-columns: 2.5rem 1fr; gap: .5rem; padding: .75rem 0; border-bottom: 1px solid rgba(255,255,255,.18); font: 700 .8rem var(--utility); text-transform: uppercase; } +.calibration-card li span { color: var(--signal); } +.calibration-note { position: relative; z-index: 1; margin: 1.25rem 0 0; color: #d1e0e1; font-size: .9rem; } + +.leaderboard-section { padding: clamp(4rem, 8vw, 8rem) clamp(1.25rem, 5vw, 5rem); } +.section-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 2rem; margin-bottom: 2.5rem; } +.updated { display: flex; align-items: center; gap: .65rem; color: var(--cyan); font: .68rem var(--utility); text-transform: uppercase; } +.pulse { width: .55rem; height: .55rem; border-radius: 50%; background: var(--success); box-shadow: 0 0 0 .3rem rgba(22,113,83,.12); } +.board-controls { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule); } +.segmented-control { display: inline-flex; } +.segmented-control button { min-height: 2.6rem; padding: 0 1rem; border: 1px solid var(--rule); background: transparent; color: var(--ink); cursor: pointer; font: 700 .7rem var(--utility); letter-spacing: .04em; text-transform: uppercase; } +.segmented-control button + button { margin-left: -1px; } +.segmented-control button[aria-pressed="true"] { position: relative; z-index: 1; border-color: var(--ink); background: var(--ink); color: white; } +.search-control { display: flex; width: min(17rem, 42vw); align-items: center; gap: .6rem; border-bottom: 1px solid var(--ink); } +.search-control:focus-within { border-bottom-color: var(--signal-dark); box-shadow: 0 3px 0 var(--signal); } +.search-control svg { width: 1rem; fill: none; stroke: currentColor; stroke-width: 1.7; } +.search-control input { width: 100%; border: 0; padding: .65rem 0; background: transparent; color: var(--ink); font: .78rem var(--utility); outline: 0; } +.comparability { margin: 1rem 0; color: #50676b; font-size: .85rem; } +.board-status { padding: 3rem 0; color: var(--cyan); font: .8rem var(--utility); } +.table-shell { overflow-x: auto; } +table { width: 100%; border-collapse: collapse; min-width: 58rem; } +th { padding: .85rem .7rem; border-bottom: 1px solid var(--ink); color: var(--cyan); font: 700 .66rem var(--utility); letter-spacing: .06em; text-align: right; text-transform: uppercase; } +th:nth-child(1), th:nth-child(2) { text-align: left; } +td { padding: 1.35rem .7rem; border-bottom: 1px solid var(--rule); text-align: right; vertical-align: middle; } +.rank { width: 3.5rem; color: #5c7073; font: 700 .82rem var(--utility); text-align: left; } +.model-cell { text-align: left; } +.model-cell strong { display: block; font: 800 1.35rem var(--display); letter-spacing: -.02em; } +.model-cell span { color: #5c7073; font: .68rem var(--utility); } +.score-cell { font: 700 .92rem var(--utility); } +.score-empty { color: var(--aluminum); } +.aggregate-cell { min-width: 11rem; } +.score-value { font: 800 1.15rem var(--utility); } +.score-rail { height: 3px; margin-top: .55rem; background: #d9e2e1; } +.score-rail span { display: block; height: 100%; background: var(--signal); } +.environment-cell { max-width: 11rem; overflow: hidden; color: #637477; font: .62rem var(--utility); text-overflow: ellipsis; white-space: nowrap; } +.assisted-board { margin-top: 2.5rem; padding: 1.25rem 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule); } +.assisted-board summary { cursor: pointer; font: 800 1.15rem var(--display); text-transform: uppercase; } +.assisted-board p { color: #50676b; } +.assisted-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem,1fr)); gap: 1rem; } +.assisted-item { padding: 1rem; background: var(--frost); } +.assisted-item strong { display: block; font-family: var(--display); } +.assisted-item span { font: .75rem var(--utility); } + +.method-section { display: grid; grid-template-columns: .8fr 1.2fr; gap: clamp(3rem, 8vw, 9rem); padding: clamp(5rem, 10vw, 10rem) clamp(1.25rem, 7vw, 8rem); background: var(--frost); border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); } +.method-intro p:last-child { max-width: 39rem; font-size: 1.15rem; line-height: 1.65; } +.method-grid { display: grid; grid-template-columns: 1fr 1fr; margin: 0; border-top: 1px solid var(--ink); border-left: 1px solid var(--rule); } +.method-grid div { min-height: 10rem; padding: 1.25rem; border-right: 1px solid var(--rule); border-bottom: 1px solid var(--rule); } +.method-grid dt { color: var(--cyan); font: .7rem var(--utility); text-transform: uppercase; } +.method-grid dd { margin: 2rem 0 0; font-size: 1rem; } +.method-grid strong { display: block; font: 800 2.4rem var(--display); } + +.submit-section { display: grid; grid-template-columns: .7fr 1.3fr; gap: clamp(3rem, 9vw, 10rem); padding: clamp(5rem, 10vw, 10rem) clamp(1.25rem, 7vw, 8rem); background: var(--paper); } +.submit-section > div:first-child > p:last-child { max-width: 34rem; font-size: 1.1rem; line-height: 1.6; } +.terminal { align-self: center; overflow: hidden; border: 1px solid #29464d; background: var(--deep); color: #dbeaea; box-shadow: .8rem .8rem 0 rgba(29,105,125,.16); } +.terminal-bar { display: flex; align-items: center; gap: .4rem; padding: .75rem 1rem; border-bottom: 1px solid rgba(255,255,255,.18); font: .65rem var(--utility); } +.terminal-bar span { width: .55rem; height: .55rem; border-radius: 50%; background: #84999c; } +.terminal-bar span:first-child { background: var(--signal); } +.terminal-bar b { margin-left: .5rem; color: #aac3c7; font-weight: 400; } +.terminal pre { overflow-x: auto; margin: 0; padding: 2rem; font-size: clamp(.7rem, 1.1vw, .86rem); line-height: 1.75; } +.terminal a { display: block; padding: 1rem 2rem; border-top: 1px solid rgba(255,255,255,.18); color: white; font: .72rem var(--utility); text-underline-offset: .25rem; } + +footer { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 2rem; padding: 2rem clamp(1.25rem, 4vw, 4.5rem); border-top: 1px solid var(--rule); font-size: .8rem; } +footer p { color: #5c7073; text-align: center; } +footer nav { display: flex; justify-self: end; gap: 1.5rem; font: .66rem var(--utility); text-transform: uppercase; } + +@media (max-width: 860px) { + .site-header { grid-template-columns: 1fr auto; } + .site-header nav { display: none; } + .hero { grid-template-columns: 1fr; } + .hero-copy { min-height: 38rem; } + .calibration-card { min-height: 31rem; } + .reticle { width: 15rem; top: 38%; } + .method-section, .submit-section { grid-template-columns: 1fr; } + footer { grid-template-columns: 1fr; } + footer p { text-align: left; } + footer nav { justify-self: start; } +} + +@media (max-width: 560px) { + .site-header { min-height: 4rem; padding: 0 1rem; } + .release-mark { font-size: .58rem; } + .hero-copy { min-height: 36rem; padding: 4rem 1.25rem; } + h1 { font-size: clamp(3rem, 15vw, 4.5rem); } + .section-heading, .board-controls { align-items: flex-start; flex-direction: column; } + .search-control { width: 100%; } + .method-grid { grid-template-columns: 1fr; } + .leaderboard-section, .method-section, .submit-section { padding-left: 1.25rem; padding-right: 1.25rem; } +} + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after { transition-duration: .01ms !important; } +} diff --git a/acidslide-v1/service/acidslide_service/static/site.js b/acidslide-v1/service/acidslide_service/static/site.js new file mode 100644 index 0000000..503fc8f --- /dev/null +++ b/acidslide-v1/service/acidslide_service/static/site.js @@ -0,0 +1,119 @@ +const state = { view: "summary", data: null, filter: "" }; + +const rows = document.querySelector("#leaderboard-rows"); +const shell = document.querySelector("#board-shell"); +const status = document.querySelector("#board-status"); +const updated = document.querySelector("#updated-at"); +const notice = document.querySelector("#comparability"); +const filter = document.querySelector("#model-filter"); +const assistedBoard = document.querySelector("#assisted-board"); +const assistedList = document.querySelector("#assisted-list"); +const assistedCount = document.querySelector("#assisted-count"); + +const text = (tag, className, value) => { + const node = document.createElement(tag); + if (className) node.className = className; + node.textContent = value; + return node; +}; + +const scoreCell = (entry, tier) => { + const cell = document.createElement("td"); + cell.className = "score-cell"; + const metric = entry.tier_scores[`level_${tier}`]; + if (!metric) { + cell.classList.add("score-empty"); + cell.textContent = "—"; + } else { + const displayed = metric.official_score ?? metric.provisional_score; + cell.textContent = displayed == null ? "—" : Number(displayed).toFixed(4); + cell.title = `${metric.submission_count}/3 occupied slot${metric.submission_count === 1 ? "" : "s"}${metric.official_score == null ? " · provisional" : " · official three-run mean"}${metric.robustness_score == null ? "" : ` · robustness ${Number(metric.robustness_score).toFixed(4)}`}`; + } + return cell; +}; + +const matching = (entry) => `${entry.model_display_name} ${entry.model_revision_display}`.toLowerCase().includes(state.filter); + +function renderRows() { + rows.replaceChildren(); + const entries = (state.data?.entries || []).filter(matching); + entries.forEach((entry, index) => { + const row = document.createElement("tr"); + row.append(text("td", "rank", String(index + 1).padStart(2, "0"))); + + const model = document.createElement("td"); + model.className = "model-cell"; + model.append(text("strong", "", entry.model_display_name), text("span", "", entry.model_revision_display)); + row.append(model, scoreCell(entry, 1), scoreCell(entry, 2), scoreCell(entry, 3)); + + const aggregate = document.createElement("td"); + aggregate.className = "aggregate-cell"; + const official = entry.aggregate_score; + aggregate.append(text("span", "score-value", official == null ? "PROV" : Number(official).toFixed(4))); + const rail = text("div", "score-rail", ""); + const fill = document.createElement("span"); + fill.style.width = `${official == null ? 0 : Math.max(0, Math.min(1, Number(official))) * 100}%`; + rail.append(fill); + aggregate.append(rail); + row.append(aggregate); + + const environment = text("td", "environment-cell", entry.scoring_cohort_id.slice(0, 19)); + environment.title = `${entry.scoring_cohort_id} · ${entry.verification_label}`; + row.append(environment); + rows.append(row); + }); + + if (!entries.length) { + status.hidden = false; + status.textContent = state.filter ? "No model matches that filter." : "No eligible grading-verified runs have been published yet."; + shell.hidden = true; + } else { + status.hidden = true; + shell.hidden = false; + } + + const assisted = (state.data?.human_assisted_entries || []).filter(matching); + assistedList.replaceChildren(); + assisted.forEach((entry) => { + const item = text("div", "assisted-item", ""); + item.append(text("strong", "", `${entry.model_display_name} · ${entry.model_revision_display}`)); + item.append(text("span", "", `${entry.aggregate_score == null ? "Provisional" : Number(entry.aggregate_score).toFixed(4)} · Level ${entry.tier}`)); + assistedList.append(item); + }); + assistedCount.textContent = assisted.length ? `(${assisted.length})` : ""; + assistedBoard.hidden = assisted.length === 0; +} + +async function loadLeaderboard() { + status.hidden = false; + shell.hidden = true; + status.textContent = "Reading the latest verified runs…"; + try { + const response = await fetch(`/v1/leaderboard?view=${state.view}`, { headers: { Accept: "application/json" } }); + if (!response.ok) throw new Error(`Leaderboard returned ${response.status}`); + state.data = await response.json(); + const timestamp = new Date(state.data.updated_at); + updated.textContent = `Updated ${timestamp.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short" })}`; + notice.textContent = state.data.comparability_notice; + renderRows(); + } catch (error) { + status.hidden = false; + status.textContent = "The leaderboard could not be loaded. Check the service status and try again."; + console.error(error); + } +} + +document.querySelectorAll("[data-view]").forEach((button) => { + button.addEventListener("click", () => { + state.view = button.dataset.view; + document.querySelectorAll("[data-view]").forEach((item) => item.setAttribute("aria-pressed", String(item === button))); + loadLeaderboard(); + }); +}); + +filter.addEventListener("input", () => { + state.filter = filter.value.trim().toLowerCase(); + renderRows(); +}); + +loadLeaderboard(); diff --git a/acidslide-v1/service/acidslide_service/storage.py b/acidslide-v1/service/acidslide_service/storage.py new file mode 100644 index 0000000..74b9170 --- /dev/null +++ b/acidslide-v1/service/acidslide_service/storage.py @@ -0,0 +1,240 @@ +"""Opaque immutable-object storage for uploads and resolved packages.""" + +from __future__ import annotations + +import asyncio +import hashlib +import os +import re +import uuid +from contextlib import suppress +from dataclasses import dataclass +from datetime import UTC, datetime +from pathlib import Path + +from fastapi import UploadFile +from sqlalchemy.orm import Session + +from acidslide_service.config import Settings +from acidslide_service.models import Artifact +from acidslide_service.quarantine_handoff import ObjectBinding + +ZIP_MAGIC = b"PK\x03\x04" +OBJECT_VERSION = re.compile(r"^objv1_[0-9a-f]{32}$") + + +class UploadTooLargeError(ValueError): + pass + + +class UploadTimeoutError(ValueError): + pass + + +class InvalidUploadError(ValueError): + pass + + +class ImmutableObjectError(ValueError): + pass + + +@dataclass(frozen=True) +class StoredUpload: + path: Path + size: int + sha256: str + object_version: str + + @property + def binding(self) -> ObjectBinding: + return ObjectBinding( + object_version=self.object_version, + sha256=f"sha256:{self.sha256}", + size_bytes=self.size, + ) + + +def new_object_version() -> str: + return f"objv1_{uuid.uuid4().hex}" + + +def ensure_storage(settings: Settings) -> None: + for directory in ( + settings.storage_path, + settings.storage_path / "staging", + settings.storage_path / "objects" / "original", + settings.storage_path / "objects" / "resolved", + settings.storage_path / "quarantine-jobs", + settings.storage_path / "artifacts", + ): + directory.mkdir(parents=True, exist_ok=True, mode=0o700) + + +def immutable_object_path( + settings: Settings, + *, + kind: str, + sha256: str, + object_version: str, +) -> Path: + if kind not in {"original", "resolved"}: + raise ImmutableObjectError("Unknown immutable object kind") + digest = sha256.removeprefix("sha256:") + if re.fullmatch(r"[0-9a-f]{64}", digest) is None: + raise ImmutableObjectError("Immutable object digest is invalid") + if OBJECT_VERSION.fullmatch(object_version) is None: + raise ImmutableObjectError("Immutable object version is invalid") + return ( + settings.storage_path / "objects" / kind / "sha256" / digest / f"{object_version}.pptx" + ).resolve() + + +def _publish_staged( + staged: Path, + settings: Settings, + *, + kind: str, + sha256: str, + object_version: str, +) -> Path: + final = immutable_object_path( + settings, + kind=kind, + sha256=sha256, + object_version=object_version, + ) + final.parent.mkdir(parents=True, exist_ok=True, mode=0o700) + try: + os.link(staged, final) + except FileExistsError as exc: + raise ImmutableObjectError("Immutable object version already exists") from exc + staged.unlink() + os.chmod(final, 0o400) + return final + + +async def store_upload(upload: UploadFile, submission_id: str, settings: Settings) -> StoredUpload: + """Stream one opaque upload while checking only transport metadata and magic bytes.""" + ensure_storage(settings) + if not (upload.filename or "").lower().endswith(".pptx"): + await upload.close() + raise InvalidUploadError("File extension must be .pptx") + object_version = new_object_version() + staging = settings.storage_path / "staging" / f"{submission_id}-{object_version}.upload" + digest = hashlib.sha256() + size = 0 + magic = bytearray() + try: + try: + async with asyncio.timeout(settings.upload_timeout_seconds): + with staging.open("xb") as destination: + os.chmod(staging, 0o600) + while chunk := await upload.read(settings.upload_chunk_bytes): + size += len(chunk) + if size > settings.max_upload_bytes: + raise UploadTooLargeError( + f"File exceeds the {settings.max_upload_bytes}-byte upload limit" + ) + if len(magic) < len(ZIP_MAGIC): + magic.extend(chunk[: len(ZIP_MAGIC) - len(magic)]) + digest.update(chunk) + destination.write(chunk) + except TimeoutError as exc: + raise UploadTimeoutError("Upload exceeded the transport timeout") from exc + if bytes(magic) != ZIP_MAGIC: + raise InvalidUploadError("The upload is not an OOXML ZIP package") + hexdigest = digest.hexdigest() + final = _publish_staged( + staging, + settings, + kind="original", + sha256=hexdigest, + object_version=object_version, + ) + return StoredUpload( + path=final, + size=size, + sha256=hexdigest, + object_version=object_version, + ) + except Exception: + staging.unlink(missing_ok=True) + raise + finally: + await upload.close() + + +def hash_file(path: Path) -> tuple[str, int]: + digest = hashlib.sha256() + size = 0 + with path.open("rb") as source: + while chunk := source.read(1024 * 1024): + size += len(chunk) + digest.update(chunk) + return digest.hexdigest(), size + + +def publish_resolved_object( + staged: Path, + settings: Settings, + binding: ObjectBinding, +) -> Path: + """Atomically commit sandbox output under its signed content address/version.""" + actual_digest, actual_size = hash_file(staged) + if binding.sha256 != f"sha256:{actual_digest}" or binding.size_bytes != actual_size: + raise ImmutableObjectError("Resolved sandbox output does not match its signed binding") + return _publish_staged( + staged, + settings, + kind="resolved", + sha256=actual_digest, + object_version=binding.object_version, + ) + + +def verify_immutable_object( + path: Path, + settings: Settings, + *, + kind: str, + binding: ObjectBinding, +) -> Path: + """Re-resolve, stat, and hash one immutable object before any package parse.""" + expected = immutable_object_path( + settings, + kind=kind, + sha256=binding.sha256, + object_version=binding.object_version, + ) + resolved = path.resolve(strict=True) + if resolved != expected or path.is_symlink() or not resolved.is_file(): + raise ImmutableObjectError("Immutable object path/version binding is invalid") + actual_digest, actual_size = hash_file(resolved) + if f"sha256:{actual_digest}" != binding.sha256 or actual_size != binding.size_bytes: + raise ImmutableObjectError("Immutable object digest or size changed") + return resolved + + +def delete_upload(path: Path) -> None: + """Delete only a known object; retained for explicit administrative cleanup.""" + path.unlink(missing_ok=True) + + +def purge_expired_artifacts(session: Session, settings: Settings) -> int: + from sqlalchemy import select + + now = datetime.now(UTC) + rows = list(session.scalars(select(Artifact).where(Artifact.expires_at < now))) + root = (settings.storage_path / "artifacts").resolve() + removed = 0 + for artifact in rows: + path = Path(artifact.storage_path).resolve() + if path.is_relative_to(root): + path.unlink(missing_ok=True) + with suppress(OSError): + path.parent.rmdir() + session.delete(artifact) + removed += 1 + session.commit() + return removed diff --git a/acidslide-v1/service/acidslide_service/webhooks.py b/acidslide-v1/service/acidslide_service/webhooks.py new file mode 100644 index 0000000..1751ea5 --- /dev/null +++ b/acidslide-v1/service/acidslide_service/webhooks.py @@ -0,0 +1,134 @@ +"""HMAC-signed webhook delivery with DNS rebinding and SSRF defenses.""" + +from __future__ import annotations + +import hashlib +import hmac +import http.client +import ipaddress +import json +import socket +import ssl +import time +from typing import Any, cast +from urllib.parse import urlparse + +from sqlalchemy.orm import Session + +from acidslide_service.config import Settings +from acidslide_service.models import Submission, WebhookDelivery +from acidslide_service.security import decrypt_secret + + +class UnsafeWebhookURLError(ValueError): + pass + + +def _resolve_webhook(value: str) -> tuple[str, int, str, list[str]]: + parsed = urlparse(value) + if parsed.scheme != "https": + raise UnsafeWebhookURLError("Webhook URL must use https://") + if not parsed.hostname or parsed.username or parsed.password or parsed.fragment: + raise UnsafeWebhookURLError("Webhook URL is not allowed") + try: + answers = socket.getaddrinfo(parsed.hostname, parsed.port or 443, type=socket.SOCK_STREAM) + except socket.gaierror as exc: + raise UnsafeWebhookURLError("Webhook hostname did not resolve") from exc + addresses = {cast(str, answer[4][0]) for answer in answers} + if not addresses: + raise UnsafeWebhookURLError("Webhook hostname did not resolve") + for resolved in addresses: + if not ipaddress.ip_address(resolved).is_global: + raise UnsafeWebhookURLError("Webhook URL resolves to a private or non-routable address") + path = parsed.path or "/" + if parsed.query: + path = f"{path}?{parsed.query}" + return parsed.hostname, parsed.port or 443, path, sorted(addresses) + + +def validate_webhook_url(value: str) -> None: + _resolve_webhook(value) + + +class _PinnedHTTPSConnection(http.client.HTTPSConnection): + """Pin a vetted IP while retaining hostname-based certificate and SNI checks.""" + + def __init__(self, hostname: str, address: str, port: int, timeout: int) -> None: + self._ssl_context = ssl.create_default_context() + super().__init__(hostname, port=port, timeout=timeout, context=self._ssl_context) + self._address = address + + def connect(self) -> None: + sock = socket.create_connection((self._address, self.port), self.timeout) + self.sock = self._ssl_context.wrap_socket(sock, server_hostname=self.host) + + +def _post_pinned(url: str, body: bytes, headers: dict[str, str]) -> int: + hostname, port, path, addresses = _resolve_webhook(url) + connection = _PinnedHTTPSConnection(hostname, addresses[0], port, timeout=10) + try: + connection.request("POST", path, body=body, headers={**headers, "Host": hostname}) + response = connection.getresponse() + response.read(1024 * 1024) + return response.status + finally: + connection.close() + + +def webhook_signature(body: bytes, secret: str) -> str: + return hmac.new(secret.encode(), body, hashlib.sha256).hexdigest() + + +def deliver_webhook( + session: Session, + submission: Submission, + payload: dict[str, Any], + settings: Settings, +) -> bool: + if not submission.webhook_url or not submission.webhook_secret_encrypted: + return True + secret = decrypt_secret(submission.webhook_secret_encrypted, settings) + body = json.dumps(payload, sort_keys=True, separators=(",", ":"), default=str).encode() + headers = { + "Content-Type": "application/json", + "X-AcidSlide-Signature": webhook_signature(body, secret), + "User-Agent": "AcidSlide-Webhook/1.0", + } + # Initial attempt plus the three OpenSpec retries at 1, 4, and 16 seconds. + for attempt, delay in enumerate((0, 1, 4, 16), start=1): + if delay: + time.sleep(delay) + try: + response_status = _post_pinned(submission.webhook_url, body, headers) + success = 200 <= response_status < 300 + outcome = ( + "delivered" + if success + else ("redirect_rejected" if 300 <= response_status < 400 else "http_error") + ) + session.add( + WebhookDelivery( + submission_id=submission.id, + attempt=attempt, + response_status=response_status, + outcome=outcome, + ) + ) + session.commit() + if success: + return True + if response_status < 500: + return False + except (http.client.HTTPException, OSError, UnsafeWebhookURLError) as exc: + session.add( + WebhookDelivery( + submission_id=submission.id, + attempt=attempt, + response_status=None, + outcome=type(exc).__name__, + ) + ) + session.commit() + if isinstance(exc, UnsafeWebhookURLError): + return False + return False diff --git a/acidslide-v1/service/acidslide_service/worker.py b/acidslide-v1/service/acidslide_service/worker.py new file mode 100644 index 0000000..2a3855b --- /dev/null +++ b/acidslide-v1/service/acidslide_service/worker.py @@ -0,0 +1,505 @@ +"""Asynchronous database-queue worker for controlled grading.""" + +from __future__ import annotations + +import logging +import os +import signal +import socket +import time +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Protocol + +from prometheus_client import Counter, Histogram, start_http_server +from sqlalchemy import select, text, update +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.canary import drift_canary_health +from acidslide_service.config import Settings, get_settings +from acidslide_service.database import SessionLocal, initialize_database +from acidslide_service.leaderboard import write_snapshot +from acidslide_service.models import QuarantineVerdictUse, Submission, WorkerHeartbeat, utcnow +from acidslide_service.quarantine_handoff import ( + ObjectBinding, + QuarantineHandoffError, + load_verification_keys, + require_binding, + verify_envelope, +) +from acidslide_service.runner import ( + DockerGradingRunner, + GradeOutcome, + GradingError, + HostedArtifactBinding, + InsecureTestRunner, + ScoringCohortBinding, +) +from acidslide_service.service import ( + claim_next_submission, + complete_submission, + fail_submission, + recover_stale_jobs, + status_payload, +) +from acidslide_service.storage import ( + ImmutableObjectError, + purge_expired_artifacts, + verify_immutable_object, +) +from acidslide_service.webhooks import deliver_webhook + +logger = logging.getLogger("acidslide.worker") +GRADES = Counter("acidslide_grades_total", "Grading outcomes", ("outcome",)) +GRADE_SECONDS = Histogram("acidslide_grading_duration_seconds", "Controlled grading duration") + + +class Runner(Protocol): + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: ... + + +def _required_string(mapping: dict[str, object], name: str) -> str: + value = mapping.get(name) + if not isinstance(value, str) or not value: + raise QuarantineHandoffError(f"Signed handoff {name} is missing") + return value + + +def _hosted_artifact_binding( + submission: Submission, + handoff: dict[str, object], +) -> HostedArtifactBinding: + """Build the exact hosted report context from signed Stage-0.5 state.""" + campaign = submission.campaign + if ( + submission.campaign_slot is None + or submission.resolved_file_sha256 is None + or submission.canonical_package_hash_v1 is None + or submission.canonical_package_hash_profile_sha256 is None + or submission.schema_validation_json is None + or submission.gold_duplicate_check_json is None + ): + raise QuarantineHandoffError("Submission lacks signed hosted report context") + + schema = submission.schema_validation_json + performed = schema.get("performed") + valid = schema.get("valid") + violations = schema.get("violations") + if not isinstance(performed, bool) or not isinstance(valid, bool): + raise QuarantineHandoffError("Signed schema validation flags are malformed") + if not isinstance(violations, list) or not all( + isinstance(violation, str) for violation in violations + ): + raise QuarantineHandoffError("Signed schema validation violations are malformed") + if not performed: + raise QuarantineHandoffError("Signed Stage 0.5 schema validation was not performed") + + gold = submission.gold_duplicate_check_json + byte_match = gold.get("byte_match") + canonical_match = gold.get("canonical_package_match") + if not isinstance(byte_match, bool) or not isinstance(canonical_match, bool): + raise QuarantineHandoffError("Signed gold duplicate flags are malformed") + gold_duplicate_check = ( + "byte_match" if byte_match else "canonical_match" if canonical_match else "clear" + ) + if gold.get("decision") != gold_duplicate_check: + raise QuarantineHandoffError("Signed gold duplicate decision is inconsistent") + + profiles_value = handoff.get("profiles") + if not isinstance(profiles_value, dict): + raise QuarantineHandoffError("Signed handoff profiles are missing") + profiles = {str(key): value for key, value in profiles_value.items()} + return HostedArtifactBinding( + prompt_variant=submission.prompt_variant, + generation_seed=submission.generation_seed, + schema_validation_performed=performed, + schema_valid=valid, + schema_violations=tuple(violations), + schema_bundle_sha256=_required_string(profiles, "schema_bundle_sha256"), + schema_root_map_sha256=_required_string(profiles, "schema_root_map_sha256"), + mce_profile_sha256=_required_string(profiles, "mce_profile_sha256"), + canonical_package_hash_profile_sha256=(submission.canonical_package_hash_profile_sha256), + canonical_package_hash_v1=submission.canonical_package_hash_v1, + gold_duplicate_check=gold_duplicate_check, + submission_sha256=f"sha256:{submission.file_sha256}", + mce_resolved_package_sha256=f"sha256:{submission.resolved_file_sha256}", + assistance_class=campaign.assistance_class, + generation_profile_sha256=campaign.generation_profile_sha256, + attested_metrics=submission.efficiency_metrics, + attestation=submission.attestation, + submission_id=submission.id, + campaign_id=submission.campaign_id, + robustness_group_id=campaign.robustness_group_id, + campaign_slot=submission.campaign_slot, + submitter_id=submission.organization_id, + model_key=submission.model_id, + model_revision_key=submission.model_revision_id, + ) + + +def _resolved_binding(submission: Submission) -> ObjectBinding: + if ( + submission.resolved_object_version is None + or submission.resolved_file_sha256 is None + or submission.resolved_file_size_bytes is None + ): + raise QuarantineHandoffError("Submission has no immutable resolved-package binding") + return ObjectBinding( + object_version=submission.resolved_object_version, + sha256=f"sha256:{submission.resolved_file_sha256}", + size_bytes=submission.resolved_file_size_bytes, + ) + + +def _original_binding(submission: Submission) -> ObjectBinding: + return ObjectBinding( + object_version=submission.original_object_version, + sha256=f"sha256:{submission.file_sha256}", + size_bytes=submission.file_size_bytes, + ) + + +def _as_utc(value: datetime) -> datetime: + return value.replace(tzinfo=UTC) if value.tzinfo is None else value.astimezone(UTC) + + +def lease_verdict( + session: Session, + *, + verdict_id: str, + submission_id: str, + worker_id: str, + lease_seconds: int, + now: datetime | None = None, +) -> int: + """Atomically lease an issued or expired signed verdict and return its generation.""" + moment = (now or datetime.now(UTC)).astimezone(UTC) + verdict = session.scalar( + select(QuarantineVerdictUse) + .where( + QuarantineVerdictUse.verdict_id == verdict_id, + QuarantineVerdictUse.submission_id == submission_id, + ) + .with_for_update() + ) + if verdict is None: + session.rollback() + raise QuarantineHandoffError("Quarantine verdict was not issued by the dispatcher") + if verdict.state == "consumed": + session.rollback() + raise QuarantineHandoffError("Quarantine verdict has already been consumed") + if verdict.state == "leased" and ( + verdict.lease_deadline is None or _as_utc(verdict.lease_deadline) > moment + ): + session.rollback() + raise QuarantineHandoffError("Quarantine verdict already has an active lease") + if verdict.state not in {"issued", "leased"}: + session.rollback() + raise QuarantineHandoffError("Quarantine verdict has an invalid lifecycle state") + + previous_state = verdict.state + previous_generation = verdict.generation + conditions = [ + QuarantineVerdictUse.verdict_id == verdict_id, + QuarantineVerdictUse.submission_id == submission_id, + QuarantineVerdictUse.state == previous_state, + QuarantineVerdictUse.generation == previous_generation, + ] + if previous_state == "leased": + conditions.append(QuarantineVerdictUse.lease_deadline <= moment) + result = session.execute( + update(QuarantineVerdictUse) + .where(*conditions) + .values( + state="leased", + generation=previous_generation + 1, + worker_id=worker_id, + lease_deadline=moment + timedelta(seconds=lease_seconds), + consumed_at=None, + ) + .execution_options(synchronize_session=False) + ) + if getattr(result, "rowcount", 0) != 1: + session.rollback() + raise QuarantineHandoffError("Quarantine verdict lease was concurrently changed") + session.commit() + session.expire_all() + return previous_generation + 1 + + +def consume_verdict( + session: Session, + *, + verdict_id: str, + submission_id: str, + worker_id: str, + generation: int, + now: datetime | None = None, +) -> None: + """Atomically consume the exact lease generation immediately before parsing.""" + moment = (now or datetime.now(UTC)).astimezone(UTC) + result = session.execute( + update(QuarantineVerdictUse) + .where( + QuarantineVerdictUse.verdict_id == verdict_id, + QuarantineVerdictUse.submission_id == submission_id, + QuarantineVerdictUse.state == "leased", + QuarantineVerdictUse.generation == generation, + QuarantineVerdictUse.worker_id == worker_id, + QuarantineVerdictUse.lease_deadline > moment, + ) + .values( + state="consumed", + lease_deadline=None, + consumed_at=moment, + ) + .execution_options(synchronize_session=False) + ) + if getattr(result, "rowcount", 0) != 1: + session.rollback() + raise QuarantineHandoffError( + "Quarantine verdict lease is expired, stale, or owned by another worker" + ) + session.commit() + session.expire_all() + + +def verify_and_consume_handoff( + session: Session, + submission: Submission, + settings: Settings, + worker_id: str, +) -> tuple[Path, dict[str, object]]: + """Verify the signed handoff and atomically consume its single-use ID.""" + if submission.campaign_slot is None or submission.resolved_file_path is None: + raise QuarantineHandoffError("Submission lost its resolved package or campaign slot") + payload = verify_envelope( + submission.quarantine_envelope_json, + load_verification_keys(settings.quarantine_verification_keys_json), + ) + resolved = _resolved_binding(submission) + if ( + submission.canonical_package_hash_v1 is None + or submission.gold_duplicate_check_json is None + or submission.schema_validation_json is None + ): + raise QuarantineHandoffError("Submission lacks signed Stage 0.5 report context") + require_binding( + payload, + original=_original_binding(submission), + resolved=resolved, + submission_id=submission.id, + campaign_id=submission.campaign_id, + campaign_slot=submission.campaign_slot, + expected_profiles={ + "canonical_package_hash_profile_sha256": ( + settings.active_canonical_package_hash_profile_sha256 + ), + "mce_profile_sha256": settings.active_mce_profile_sha256, + "quarantine_profile_sha256": settings.active_quarantine_profile_sha256, + "schema_bundle_sha256": settings.active_schema_bundle_sha256, + "schema_root_map_sha256": settings.active_schema_root_map_sha256, + }, + expected_context={ + "canonical_package_hash_v1": submission.canonical_package_hash_v1, + "control_authorization_object_version": None, + "control_authorization_sha256": None, + "gold_duplicate_check": submission.gold_duplicate_check_json, + "run_kind": "submission", + "schema_validation": submission.schema_validation_json, + }, + ) + resolved_path = verify_immutable_object( + Path(submission.resolved_file_path), + settings, + kind="resolved", + binding=resolved, + ) + verdict_id = str(payload["verdict_id"]) + generation = lease_verdict( + session, + verdict_id=verdict_id, + submission_id=submission.id, + worker_id=worker_id, + lease_seconds=settings.stale_job_seconds, + ) + consume_verdict( + session, + verdict_id=verdict_id, + submission_id=submission.id, + worker_id=worker_id, + generation=generation, + ) + session.refresh(submission) + return resolved_path, payload + + +def worker_once( + settings: Settings, + sessions: sessionmaker[Session], + runner: Runner, + worker_id: str, +) -> bool: + with sessions() as session: + if settings.app_env == "production": + canary = drift_canary_health(session, settings) + if not canary.ready: + logger.error( + "Grading blocked by drift canary code=%s run_id=%s", + canary.code, + canary.run_id, + ) + return False + submission = claim_next_submission(session, settings, worker_id) + if submission is None: + return False + started = time.monotonic() + try: + resolved_path, handoff = verify_and_consume_handoff( + session, submission, settings, worker_id + ) + campaign = submission.campaign + outcome = runner.grade( + resolved_path, + submission.tier, + submission.id, + ScoringCohortBinding( + scoring_cohort_id=campaign.scoring_cohort_id, + scoring_manifest_sha256=campaign.scoring_manifest_sha256, + grader_source_tree_sha256=campaign.grader_source_tree_sha256, + environment_attestation_sha256=campaign.environment_attestation_sha256, + ), + _hosted_artifact_binding(submission, handoff), + ) + profiles = handoff["profiles"] + assert isinstance(profiles, dict) + provenance = { + **outcome.provenance, + "original_object_version": submission.original_object_version, + "original_sha256": f"sha256:{submission.file_sha256}", + "quarantine_key_id": str(handoff["key_id"]), + "quarantine_verdict_id": str(handoff["verdict_id"]), + "resolved_object_version": str(submission.resolved_object_version), + "resolved_sha256": f"sha256:{submission.resolved_file_sha256}", + **{str(name): str(value) for name, value in profiles.items()}, + } + complete_submission( + session, + submission, + outcome.report, + provenance, + outcome.artifacts, + settings.artifact_retention_days, + ) + GRADES.labels("completed").inc() + except (QuarantineHandoffError, ImmutableObjectError) as exc: + fail_submission( + session, + submission, + code="quarantine_handoff_mismatch", + message=str(exc), + retryable=False, + ) + GRADES.labels("quarantine_handoff_mismatch").inc() + except GradingError as exc: + fail_submission( + session, + submission, + code=exc.code, + message=str(exc), + retryable=exc.retryable, + ) + GRADES.labels(exc.code).inc() + except Exception as exc: + logger.exception("Unexpected grading failure submission_id=%s", submission.id) + fail_submission( + session, + submission, + code="grading_failed", + message=f"Controlled grader failed: {type(exc).__name__}", + retryable=False, + ) + GRADES.labels("grading_failed").inc() + finally: + GRADE_SECONDS.observe(time.monotonic() - started) + session.refresh(submission) + if submission.status == "completed": + try: + write_snapshot(session, settings, submission.benchmark_version) + except Exception: + session.rollback() + logger.exception("Leaderboard snapshot failed submission_id=%s", submission.id) + if submission.webhook_url: + try: + deliver_webhook(session, submission, status_payload(submission), settings) + except Exception: + session.rollback() + logger.exception("Webhook delivery failed submission_id=%s", submission.id) + return True + + +def run() -> None: + logging.basicConfig(level=logging.INFO) + settings = get_settings() + if settings.app_env == "production": + with SessionLocal() as session: + session.execute(text("SELECT version_num FROM alembic_version")) + else: + initialize_database() + start_http_server(settings.worker_metrics_port) + worker_id = f"grading:{socket.gethostname()}:{os.getpid()}" + runner: Runner + if settings.allow_insecure_test_runner: + runner = InsecureTestRunner(settings) + else: + runner = DockerGradingRunner(settings) + stopping = False + + def stop(_signum: int, _frame: object) -> None: + nonlocal stopping + stopping = True + + signal.signal(signal.SIGTERM, stop) + signal.signal(signal.SIGINT, stop) + with SessionLocal() as session: + recovered = recover_stale_jobs(session, settings) + if recovered: + logger.warning("Recovered %s stale grading jobs", recovered) + logger.info("Worker started worker_id=%s", worker_id) + last_heartbeat = 0.0 + last_retention_sweep = 0.0 + while not stopping: + now = time.monotonic() + if now - last_heartbeat >= settings.worker_heartbeat_seconds: + with SessionLocal() as session: + heartbeat = session.get(WorkerHeartbeat, worker_id) + if heartbeat is None: + heartbeat = WorkerHeartbeat( + worker_id=worker_id, + hostname=socket.gethostname(), + process_id=os.getpid(), + ) + session.add(heartbeat) + heartbeat.last_seen_at = utcnow() + session.commit() + last_heartbeat = now + if now - last_retention_sweep >= 3600: + with SessionLocal() as session: + removed = purge_expired_artifacts(session, settings) + if removed: + logger.info("Purged %s expired private artifacts", removed) + last_retention_sweep = now + if not worker_once(settings, SessionLocal, runner, worker_id): + time.sleep(settings.worker_poll_seconds) + logger.info("Worker stopped worker_id=%s", worker_id) + + +if __name__ == "__main__": + run() diff --git a/acidslide-v1/service/alembic.ini b/acidslide-v1/service/alembic.ini new file mode 100644 index 0000000..7602837 --- /dev/null +++ b/acidslide-v1/service/alembic.ini @@ -0,0 +1,31 @@ +[alembic] +script_location = alembic +prepend_sys_path = . +sqlalchemy.url = sqlite:///./acidslide-service.db + +[loggers] +keys = root,sqlalchemy,alembic +[handlers] +keys = console +[formatters] +keys = generic +[logger_root] +level = WARN +handlers = console +qualname = +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine +[logger_alembic] +level = INFO +handlers = +qualname = alembic +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/acidslide-v1/service/alembic/env.py b/acidslide-v1/service/alembic/env.py new file mode 100644 index 0000000..8d01d83 --- /dev/null +++ b/acidslide-v1/service/alembic/env.py @@ -0,0 +1,39 @@ +from logging.config import fileConfig + +from acidslide_service import models # noqa: F401 +from acidslide_service.config import get_settings +from acidslide_service.database import Base +from alembic import context + +config = context.config +if config.config_file_name is not None: + fileConfig(config.config_file_name) +config.set_main_option("sqlalchemy.url", get_settings().database_url.replace("%", "%%")) +target_metadata = Base.metadata + + +def run_migrations_offline() -> None: + context.configure( + url=config.get_main_option("sqlalchemy.url"), + target_metadata=target_metadata, + literal_binds=True, + dialect_opts={"paramstyle": "named"}, + ) + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online() -> None: + from sqlalchemy import create_engine + + connectable = create_engine(config.get_main_option("sqlalchemy.url"), pool_pre_ping=True) + with connectable.connect() as connection: + context.configure(connection=connection, target_metadata=target_metadata) + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/acidslide-v1/service/alembic/script.py.mako b/acidslide-v1/service/alembic/script.py.mako new file mode 100644 index 0000000..ec350b4 --- /dev/null +++ b/acidslide-v1/service/alembic/script.py.mako @@ -0,0 +1,21 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} +""" +from typing import Sequence, Union +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +revision: str = ${repr(up_revision)} +down_revision: Union[str, None] = ${repr(down_revision)} +branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} +depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} + +def upgrade() -> None: + ${upgrades if upgrades else "pass"} + +def downgrade() -> None: + ${downgrades if downgrades else "pass"} diff --git a/acidslide-v1/service/alembic/versions/20260718_0001_initial.py b/acidslide-v1/service/alembic/versions/20260718_0001_initial.py new file mode 100644 index 0000000..b86c05f --- /dev/null +++ b/acidslide-v1/service/alembic/versions/20260718_0001_initial.py @@ -0,0 +1,26 @@ +"""Initial pre-release hosted-service schema. + +The service has not been deployed. This first revision therefore freezes the complete v1 identity, +campaign, robustness-group, reserved-slot, and immutable-run schema rather than preserving the +superseded free-text prototype layout. + +Revision ID: 20260718_0001 +Revises: +""" + +from acidslide_service import models # noqa: F401 +from acidslide_service.database import Base +from alembic import op + +revision = "20260718_0001" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade() -> None: + Base.metadata.create_all(bind=op.get_bind()) + + +def downgrade() -> None: + Base.metadata.drop_all(bind=op.get_bind()) diff --git a/acidslide-v1/service/api-spec.yaml b/acidslide-v1/service/api-spec.yaml new file mode 100644 index 0000000..f5f0cdf --- /dev/null +++ b/acidslide-v1/service/api-spec.yaml @@ -0,0 +1,774 @@ +openapi: 3.1.0 +info: + title: AcidSlide hosted service + version: 1.0.0 + description: Controlled grading and the public grading-verified AcidSlide leaderboard. +servers: + - url: https://api.acidslide.dev/v1 + - url: http://localhost:8000/v1 +tags: + - name: identity + - name: campaigns + - name: submissions + - name: leaderboard + - name: benchmark + - name: admin +paths: + /versions: + get: + tags: [benchmark] + operationId: listVersions + responses: + "200": + description: Active and frozen benchmark versions. + content: + application/json: + schema: + type: object + required: [active, frozen, active_scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256] + properties: + active: {type: array, items: {type: string}} + frozen: {type: array, items: {type: string}} + active_scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + /models: + post: + tags: [identity] + operationId: createModelIdentity + security: [{apiKey: []}] + requestBody: + required: true + content: + application/json: {schema: {$ref: "#/components/schemas/ModelCreate"}} + responses: + "201": + description: Server-issued immutable model identity. + content: + application/json: {schema: {$ref: "#/components/schemas/ModelIdentity"}} + "401": {$ref: "#/components/responses/Unauthorized"} + /models/{model_key}/revisions: + post: + tags: [identity] + operationId: createModelRevision + security: [{apiKey: []}] + parameters: + - name: model_key + in: path + required: true + schema: {type: string, format: uuid} + requestBody: + required: true + content: + application/json: {schema: {$ref: "#/components/schemas/ModelRevisionCreate"}} + responses: + "201": + description: Server-issued immutable model revision. + content: + application/json: {schema: {$ref: "#/components/schemas/ModelRevision"}} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + /generation-profiles: + post: + tags: [identity] + operationId: createGenerationProfile + description: Validate, RFC 8785 hash, and immutably register a generation profile. + security: [{apiKey: []}] + requestBody: + required: true + content: + application/json: {schema: {$ref: "#/components/schemas/GenerationProfileCreate"}} + responses: + "201": + description: Immutable tenant/revision-scoped generation profile. + content: + application/json: {schema: {$ref: "#/components/schemas/GenerationProfile"}} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + "409": {description: Digest is already registered in another scope.} + "422": {$ref: "#/components/responses/Rejected"} + /campaigns: + post: + tags: [campaigns] + operationId: createCampaign + security: [{apiKey: []}] + requestBody: + required: true + content: + application/json: {schema: {$ref: "#/components/schemas/CampaignCreate"}} + responses: + "201": + description: Immutable seven-day single-variant campaign. + content: + application/json: {schema: {$ref: "#/components/schemas/Campaign"}} + "401": {$ref: "#/components/responses/Unauthorized"} + "409": {description: Campaign already exists in the active window.} + "422": {$ref: "#/components/responses/Rejected"} + /campaigns/{campaign_id}: + get: + tags: [campaigns] + operationId: getCampaign + security: [{apiKey: []}, {}] + parameters: + - name: campaign_id + in: path + required: true + schema: {type: string, format: uuid} + responses: + "200": + description: Immutable campaign binding and ordered slot state. + content: + application/json: {schema: {$ref: "#/components/schemas/Campaign"}} + "404": {$ref: "#/components/responses/NotFound"} + /robustness-groups: + post: + tags: [campaigns] + operationId: createRobustnessGroup + security: [{apiKey: []}] + requestBody: + required: true + content: + application/json: {schema: {$ref: "#/components/schemas/RobustnessGroupCreate"}} + responses: + "201": + description: Atomic three-variant campaign group. + content: + application/json: {schema: {$ref: "#/components/schemas/RobustnessGroup"}} + "401": {$ref: "#/components/responses/Unauthorized"} + "409": {description: A child campaign already exists in the active window.} + "422": {$ref: "#/components/responses/Rejected"} + /robustness-groups/{robustness_group_id}: + get: + tags: [campaigns] + operationId: getRobustnessGroup + parameters: + - name: robustness_group_id + in: path + required: true + schema: {type: string, format: uuid} + responses: + "200": + description: Three child campaign statuses and robustness result. + content: + application/json: {schema: {$ref: "#/components/schemas/RobustnessGroup"}} + "404": {$ref: "#/components/responses/NotFound"} + /submissions: + post: + tags: [submissions] + operationId: createSubmission + security: [{apiKey: []}] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: [metadata, file] + properties: + metadata: + type: string + contentMediaType: application/json + description: JSON-encoded SubmissionMetadata. + file: + type: string + format: binary + description: OOXML PowerPoint deck, at most 100 MB. + responses: + "202": + description: Opaque upload stored and reserved for disposable quarantine. + content: + application/json: + schema: {$ref: "#/components/schemas/SubmissionAccepted"} + "401": {$ref: "#/components/responses/Unauthorized"} + "413": {$ref: "#/components/responses/FileTooLarge"} + "422": {$ref: "#/components/responses/Rejected"} + "429": + description: Submission rate or quota limit reached. + headers: + Retry-After: + schema: {type: integer} + description: Seconds until the limiting window releases. + content: + application/json: + schema: {$ref: "#/components/schemas/ErrorEnvelope"} + /submissions/{submission_id}: + parameters: + - $ref: "#/components/parameters/SubmissionId" + get: + tags: [submissions] + operationId: getSubmission + security: [{apiKey: []}] + responses: + "200": + description: Current job state and the result when completed. + content: + application/json: + schema: {$ref: "#/components/schemas/SubmissionStatus"} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + /submissions/{submission_id}/report: + parameters: + - $ref: "#/components/parameters/SubmissionId" + - name: format + in: query + schema: {type: string, enum: [json, html], default: json} + get: + tags: [submissions] + operationId: getReport + description: Private to the submitting organization unless permanently published. + security: [{apiKey: []}, {}] + responses: + "200": + description: Full grading report. + content: + application/json: {schema: {type: object}} + text/html: {schema: {type: string}} + "404": {$ref: "#/components/responses/NotFound"} + /submissions/{submission_id}/publish-report: + parameters: + - $ref: "#/components/parameters/SubmissionId" + post: + tags: [submissions] + operationId: publishReport + description: Permanently make a completed full report public. This cannot be reversed. + security: [{apiKey: []}] + responses: + "200": + description: Report is public. + content: + application/json: + schema: + type: object + required: [submission_id, report_public, report_url] + properties: + submission_id: {type: string, format: uuid} + report_public: {const: true} + report_url: {type: string} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + /submissions/{submission_id}/artifacts: + parameters: + - $ref: "#/components/parameters/SubmissionId" + get: + tags: [submissions] + operationId: listSubmissionArtifacts + description: List private per-slide diff artifacts retained for 90 days. + security: [{apiKey: []}] + responses: + "200": {description: Private artifact metadata and authenticated URLs.} + "401": {$ref: "#/components/responses/Unauthorized"} + /submissions/{submission_id}/artifacts/{artifact_name}: + parameters: + - $ref: "#/components/parameters/SubmissionId" + - name: artifact_name + in: path + required: true + schema: {type: string, pattern: '^diff-slide-[0-9]{2}\\.png$'} + get: + tags: [submissions] + operationId: getSubmissionArtifact + description: Download one private per-slide PNG diff before its retention expiry. + security: [{apiKey: []}] + responses: + "200": + description: PNG diff artifact. + content: + image/png: {schema: {type: string, format: binary}} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + /leaderboard: + get: + tags: [leaderboard] + operationId: getLeaderboard + parameters: + - name: view + in: query + schema: {type: string, enum: [summary, detail], default: summary} + - name: benchmark_version + in: query + schema: {type: string} + responses: + "200": + description: Public grading-verified score aggregates. + content: + application/json: + schema: {$ref: "#/components/schemas/Leaderboard"} + "404": {$ref: "#/components/responses/NotFound"} + /leaderboard/history: + get: + tags: [leaderboard] + operationId: getLeaderboardHistory + parameters: + - name: benchmark_version + in: query + schema: {type: string} + - name: limit + in: query + schema: {type: integer, minimum: 1, maximum: 100, default: 30} + - name: offset + in: query + schema: {type: integer, minimum: 0, default: 0} + responses: + "200": + description: Historical immutable leaderboard snapshots. + content: + application/json: {schema: {type: object}} + /leaderboard/runs: + get: + tags: [leaderboard] + operationId: getLeaderboardRuns + parameters: + - name: benchmark_version + in: query + schema: {type: string} + - name: limit + in: query + schema: {type: integer, minimum: 1, maximum: 500, default: 100} + - name: offset + in: query + schema: {type: integer, minimum: 0, default: 0} + responses: + "200": + description: Append-only public completed grading-run ledger. + content: + application/json: + schema: {$ref: "#/components/schemas/PublicRunLedger"} + /admin/organizations: + get: + tags: [admin] + operationId: listOrganizations + security: [{adminKey: []}] + responses: + "200": {description: Organizations without secret material.} + "401": {$ref: "#/components/responses/Unauthorized"} + post: + tags: [admin] + operationId: createOrganization + description: The generated API key is returned once. + security: [{adminKey: []}] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: {type: string, minLength: 1, maxLength: 160} + monthly_quota: {type: integer, minimum: 1, default: 30} + is_paid: {type: boolean, default: false} + responses: + "201": {description: Organization and one-time API key.} + "401": {$ref: "#/components/responses/Unauthorized"} + "409": {description: Organization name already exists.} + /admin/organizations/{organization_id}: + parameters: + - name: organization_id + in: path + required: true + schema: {type: string, format: uuid} + patch: + tags: [admin] + operationId: updateOrganization + security: [{adminKey: []}] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + is_suspended: {type: boolean} + monthly_quota: {type: integer, minimum: 1} + responses: + "200": {description: Updated organization controls.} + "401": {$ref: "#/components/responses/Unauthorized"} + "404": {$ref: "#/components/responses/NotFound"} + /admin/jobs: + get: + tags: [admin] + operationId: getJobCounts + security: [{adminKey: []}] + responses: + "200": {description: Queue counts by status.} + "401": {$ref: "#/components/responses/Unauthorized"} +components: + securitySchemes: + apiKey: + type: http + scheme: bearer + bearerFormat: AcidSlide API key + adminKey: + type: apiKey + in: header + name: X-Admin-Key + parameters: + SubmissionId: + name: submission_id + in: path + required: true + schema: {type: string, format: uuid} + responses: + Unauthorized: + description: Authentication failed. + content: + application/json: {schema: {$ref: "#/components/schemas/ErrorEnvelope"}} + NotFound: + description: Resource not found or not visible to this principal. + content: + application/json: {schema: {$ref: "#/components/schemas/ErrorEnvelope"}} + FileTooLarge: + description: File exceeds 100 MB. + content: + application/json: {schema: {$ref: "#/components/schemas/ErrorEnvelope"}} + Rejected: + description: Invalid metadata, benchmark version, tier, webhook, or quarantine failure. + content: + application/json: {schema: {$ref: "#/components/schemas/ErrorEnvelope"}} + schemas: + Sha256: + type: string + pattern: '^sha256:[0-9a-f]{64}$' + VerificationScope: + const: artifact_conformance + VerificationLabel: + const: grading-verified artifact score; generation-attested + ErrorEnvelope: + type: object + required: [detail] + properties: + detail: + oneOf: + - type: string + - type: object + properties: + code: {type: string} + message: {type: string} + retryable: {type: boolean} + ModelCreate: + type: object + additionalProperties: false + required: [display_name] + properties: + display_name: {type: string, minLength: 1, maxLength: 160} + owner_attribution: + type: string + enum: [owner-verified, submitter-attested] + default: submitter-attested + ModelIdentity: + type: object + required: [submitter_id, model_key, display_name, owner_attribution, created_at] + properties: + submitter_id: {type: string, format: uuid} + model_key: {type: string, format: uuid} + display_name: {type: string} + owner_attribution: {type: string, enum: [owner-verified, submitter-attested]} + created_at: {type: string, format: date-time} + ModelRevisionCreate: + type: object + additionalProperties: false + required: [display_version, revision_note] + properties: + display_version: {type: string, minLength: 1, maxLength: 160} + revision_note: {type: string, minLength: 1, maxLength: 4000} + provider_revision: {type: [string, "null"], minLength: 1, maxLength: 320} + ModelRevision: + type: object + required: [model_key, model_revision_key, display_version, revision_note, created_at] + properties: + model_key: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + display_version: {type: string} + revision_note: {type: string} + created_at: {type: string, format: date-time} + GenerationProfileCreate: + type: object + additionalProperties: false + required: [model_revision_key, profile] + properties: + model_revision_key: {type: string, format: uuid} + profile: {type: object} + GenerationProfile: + type: object + required: [generation_profile_sha256, submitter_id, model_revision_key, profile, created_at] + properties: + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + submitter_id: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + profile: {type: object} + created_at: {type: string, format: date-time} + CampaignCreate: + type: object + additionalProperties: false + required: [model_revision_key, scoring_cohort_id, tier, prompt_variant, assistance_class, generation_profile_sha256] + properties: + model_revision_key: {type: string, format: uuid} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + tier: {type: integer, enum: [1, 2, 3]} + prompt_variant: {type: string, enum: [canonical, paraphrase-a, paraphrase-b]} + assistance_class: {type: string, enum: [unassisted, human-assisted]} + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + CampaignSlot: + type: object + required: [campaign_slot, submission_id, status] + properties: + campaign_slot: {type: integer, enum: [1, 2, 3]} + submission_id: {type: string, format: uuid} + status: {type: string, enum: [queued, grading, completed]} + run_id: {type: [string, "null"], format: uuid} + campaign_score: {type: [number, "null"], minimum: 0, maximum: 1} + Campaign: + type: object + required: [campaign_id, submitter_id, model_key, model_revision_key, tier, benchmark_version, prompt_variant, assistance_class, generation_profile_sha256, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256, window_id, opens_at, closes_at, slot_count, occupied_slots, status, slots, public_run_ids] + properties: + campaign_id: {type: string, format: uuid} + robustness_group_id: {type: [string, "null"], format: uuid} + submitter_id: {type: string, format: uuid} + model_key: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + tier: {type: integer, enum: [1, 2, 3]} + benchmark_version: {type: string} + prompt_variant: {type: string, enum: [canonical, paraphrase-a, paraphrase-b]} + assistance_class: {type: string, enum: [unassisted, human-assisted]} + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + window_id: {type: string, format: uuid} + opens_at: {type: string, format: date-time} + closes_at: {type: string, format: date-time} + slot_count: {const: 3} + occupied_slots: {type: integer, minimum: 0, maximum: 3} + status: {type: string, enum: [open, provisional, closed-incomplete, completed]} + slots: {type: array, items: {$ref: "#/components/schemas/CampaignSlot"}} + public_run_ids: {type: array, items: {type: string, format: uuid}} + official_score: {type: [number, "null"], minimum: 0, maximum: 1} + best_score: {type: [number, "null"], minimum: 0, maximum: 1} + worst_score: {type: [number, "null"], minimum: 0, maximum: 1} + standard_deviation: {type: [number, "null"], minimum: 0} + verification_scope: + oneOf: [{$ref: "#/components/schemas/VerificationScope"}, {type: "null"}] + verification_label: + oneOf: [{$ref: "#/components/schemas/VerificationLabel"}, {type: "null"}] + RobustnessGroupCreate: + type: object + additionalProperties: false + required: [model_revision_key, scoring_cohort_id, tier, assistance_class, generation_profile_sha256] + properties: + model_revision_key: {type: string, format: uuid} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + tier: {type: integer, enum: [1, 2, 3]} + assistance_class: {type: string, enum: [unassisted, human-assisted]} + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + RobustnessGroup: + type: object + required: [robustness_group_id, submitter_id, model_key, model_revision_key, tier, assistance_class, generation_profile_sha256, benchmark_version, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256, window_id, opens_at, closes_at, campaigns, campaign_statuses, status] + properties: + robustness_group_id: {type: string, format: uuid} + submitter_id: {type: string, format: uuid} + model_key: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + tier: {type: integer, enum: [1, 2, 3]} + assistance_class: {type: string, enum: [unassisted, human-assisted]} + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + benchmark_version: {type: string} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + window_id: {type: string, format: uuid} + opens_at: {type: string, format: date-time} + closes_at: {type: string, format: date-time} + campaigns: + type: object + required: [canonical, paraphrase-a, paraphrase-b] + additionalProperties: {type: string, format: uuid} + campaign_statuses: {type: object, additionalProperties: {type: string}} + status: {type: string, enum: [open, provisional, closed-incomplete, completed]} + robustness_score: {type: [number, "null"], minimum: 0, maximum: 1} + cross_variant_mean: {type: [number, "null"], minimum: 0, maximum: 1} + cross_variant_standard_deviation: {type: [number, "null"], minimum: 0} + SubmissionAccepted: + type: object + required: [submission_id, campaign_id, campaign_slot, status, estimated_wait_seconds, status_url] + properties: + submission_id: {type: string, format: uuid} + campaign_id: {type: string, format: uuid} + campaign_slot: {type: integer, enum: [1, 2, 3]} + status: {const: quarantining} + estimated_wait_seconds: {type: integer, minimum: 0} + status_url: {type: string} + SubmissionStatus: + type: object + required: [submission_id, campaign_id, campaign_slot, status, created_at] + properties: + submission_id: {type: string, format: uuid} + campaign_id: {type: string, format: uuid} + campaign_slot: {type: [integer, "null"], minimum: 1, maximum: 3} + status: {type: string, enum: [quarantining, queued, grading, completed, failed, rejected]} + result: {$ref: "#/components/schemas/SubmissionResult"} + error: + type: object + properties: + code: {type: string} + message: {type: string} + retryable: {type: boolean} + created_at: {type: string, format: date-time} + grading_started_at: {type: [string, "null"], format: date-time} + grading_completed_at: {type: [string, "null"], format: date-time} + SubmissionResult: + type: object + required: [fidelity_score, passed_items, total_items, deck_passed, eligible, anti_cheat_flags, repair_triggered, tier_scores, report_url, campaign_id, campaign_slot, campaign_score, verification_scope, verification_label, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256] + properties: + fidelity_score: {type: [number, "null"], minimum: 0, maximum: 1} + passed_items: {type: integer, minimum: 0} + total_items: {type: integer, minimum: 0} + deck_passed: {type: boolean} + eligible: {type: boolean} + anti_cheat_flags: {type: array} + repair_triggered: {type: boolean} + tier_scores: {type: object} + report_url: {type: string} + environment_hash: {type: string} + campaign_id: {type: string, format: uuid} + campaign_slot: {type: integer, enum: [1, 2, 3]} + campaign_score: {type: number, minimum: 0, maximum: 1} + verification_scope: {$ref: "#/components/schemas/VerificationScope"} + verification_label: {$ref: "#/components/schemas/VerificationLabel"} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + TierScore: + type: [object, "null"] + properties: + official_score: {type: [number, "null"]} + provisional_score: {type: [number, "null"]} + record_score: {type: [number, "null"]} + best_score: {type: [number, "null"]} + mean_score: {type: number} + worst_score: {type: number} + submission_count: {type: integer} + robustness_score: {type: [number, "null"]} + standard_deviation: {type: [number, "null"]} + LeaderboardEntry: + type: object + required: [verification_scope, verification_label, submitter_id, model_key, model_revision_key, campaign_id, model_display_name, model_revision_display, owner_attribution, tier, benchmark_version, prompt_variant, tier_scores, aggregate_score, provisional, ranked, stale, human_assisted, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256] + properties: + verification_scope: {$ref: "#/components/schemas/VerificationScope"} + verification_label: {$ref: "#/components/schemas/VerificationLabel"} + submitter_id: {type: string, format: uuid} + model_key: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + campaign_id: {type: string, format: uuid} + model_display_name: {type: string} + model_revision_display: {type: string} + owner_attribution: {type: string, enum: [owner-verified, submitter-attested]} + tier: {type: integer, enum: [1, 2, 3]} + benchmark_version: {type: string} + prompt_variant: {type: string, enum: [canonical, paraphrase-a, paraphrase-b]} + tier_scores: + type: object + properties: + level_1: {$ref: "#/components/schemas/TierScore"} + level_2: {$ref: "#/components/schemas/TierScore"} + level_3: {$ref: "#/components/schemas/TierScore"} + aggregate_score: {type: [number, "null"], minimum: 0, maximum: 1} + provisional: {type: boolean} + ranked: {type: boolean} + stale: {type: boolean} + human_assisted: {type: boolean} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + Leaderboard: + type: object + required: [benchmark_version, verification_scope, verification_label, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256, updated_at, view, entries, human_assisted_entries, comparability_notice] + properties: + benchmark_version: {type: string} + verification_scope: {$ref: "#/components/schemas/VerificationScope"} + verification_label: {$ref: "#/components/schemas/VerificationLabel"} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + updated_at: {type: string, format: date-time} + view: {type: string, enum: [summary, detail]} + entries: {type: array, items: {$ref: "#/components/schemas/LeaderboardEntry"}} + human_assisted_entries: {type: array, items: {$ref: "#/components/schemas/LeaderboardEntry"}} + comparability_notice: {type: string} + PublicRunLedger: + type: object + required: [benchmark_version, verification_scope, verification_label, total, runs] + properties: + benchmark_version: {type: string} + verification_scope: {$ref: "#/components/schemas/VerificationScope"} + verification_label: {$ref: "#/components/schemas/VerificationLabel"} + total: {type: integer, minimum: 0} + runs: {type: array, items: {$ref: "#/components/schemas/PublicRun"}} + PublicRun: + type: object + required: [verification_scope, verification_label, grading_mode, run_kind, submission_id, run_id, submitter_id, model_key, model_revision_key, campaign_id, campaign_slot, tier, benchmark_version, prompt_variant, assistance_class, generation_profile_sha256, scoring_cohort_id, scoring_manifest_sha256, grader_source_tree_sha256, environment_attestation_sha256, grader_package_sha256, oci_image_digest, prompt_bundle_sha256, scored_assertion_inventory_sha256, checklist_bundle_sha256, schema_bundle_sha256, schema_root_map_sha256, mce_profile_sha256, asset_manifest_sha256, font_manifest_sha256, submission_sha256, mce_resolved_package_sha256, canonical_package_hash_profile_sha256, canonical_package_hash_v1, gold_submission_sha256, gold_mce_resolved_package_sha256, gold_canonical_package_hash_v1, gold_duplicate_check, fidelity_score, campaign_score, campaign_contribution, eligible, schema_validation_performed, schema_valid, verification_complete, scoring_completed, report_sha256, environment_attestation, generation_attestation, attested_efficiency, submitted_at, grading_started_at, grading_completed_at] + properties: + verification_scope: {$ref: "#/components/schemas/VerificationScope"} + verification_label: {$ref: "#/components/schemas/VerificationLabel"} + grading_mode: {const: hosted} + run_kind: {const: submission} + submission_id: {type: string, format: uuid} + run_id: {type: string, format: uuid} + submitter_id: {type: string, format: uuid} + model_key: {type: string, format: uuid} + model_revision_key: {type: string, format: uuid} + campaign_id: {type: string, format: uuid} + robustness_group_id: {type: [string, "null"], format: uuid} + campaign_slot: {type: integer, enum: [1, 2, 3]} + tier: {type: integer, enum: [1, 2, 3]} + benchmark_version: {type: string} + prompt_variant: {type: string, enum: [canonical, paraphrase-a, paraphrase-b]} + assistance_class: {type: string, enum: [unassisted, human-assisted]} + generation_profile_sha256: {$ref: "#/components/schemas/Sha256"} + generation_seed: {type: [string, "null"]} + scoring_cohort_id: {$ref: "#/components/schemas/Sha256"} + scoring_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + grader_source_tree_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation_sha256: {$ref: "#/components/schemas/Sha256"} + grader_package_sha256: {$ref: "#/components/schemas/Sha256"} + oci_image_digest: {$ref: "#/components/schemas/Sha256"} + prompt_bundle_sha256: {$ref: "#/components/schemas/Sha256"} + scored_assertion_inventory_sha256: {$ref: "#/components/schemas/Sha256"} + checklist_bundle_sha256: {$ref: "#/components/schemas/Sha256"} + schema_bundle_sha256: {$ref: "#/components/schemas/Sha256"} + schema_root_map_sha256: {$ref: "#/components/schemas/Sha256"} + mce_profile_sha256: {$ref: "#/components/schemas/Sha256"} + asset_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + font_manifest_sha256: {$ref: "#/components/schemas/Sha256"} + submission_sha256: {$ref: "#/components/schemas/Sha256"} + mce_resolved_package_sha256: {$ref: "#/components/schemas/Sha256"} + canonical_package_hash_profile_sha256: {$ref: "#/components/schemas/Sha256"} + canonical_package_hash_v1: {$ref: "#/components/schemas/Sha256"} + gold_submission_sha256: {$ref: "#/components/schemas/Sha256"} + gold_mce_resolved_package_sha256: {$ref: "#/components/schemas/Sha256"} + gold_canonical_package_hash_v1: {$ref: "#/components/schemas/Sha256"} + gold_duplicate_check: {type: string, enum: [clear, byte_match, canonical_match, incomplete]} + fidelity_score: {type: [number, "null"], minimum: 0, maximum: 1} + campaign_score: {type: number, minimum: 0, maximum: 1} + campaign_contribution: {type: number, minimum: 0, maximum: 1} + eligible: {type: boolean} + schema_validation_performed: {type: boolean} + schema_valid: {type: boolean} + visual_verification_performed: {type: [boolean, "null"]} + verification_complete: {type: boolean} + scoring_completed: {type: boolean} + disqualification_state: {type: [string, "null"]} + ineligibility_reasons: {type: array, items: {type: string}} + score_semantic_report_sha256: {type: [string, "null"], pattern: '^sha256:[0-9a-f]{64}$'} + report_sha256: {$ref: "#/components/schemas/Sha256"} + environment_attestation: {type: object} + generation_attestation: {type: object} + attested_efficiency: {type: object} + submitted_at: {type: string, format: date-time} + grading_started_at: {type: string, format: date-time} + grading_completed_at: {type: string, format: date-time} diff --git a/acidslide-v1/service/compose.yaml b/acidslide-v1/service/compose.yaml new file mode 100644 index 0000000..8515a76 --- /dev/null +++ b/acidslide-v1/service/compose.yaml @@ -0,0 +1,171 @@ +name: acidslide + +services: + postgres: + image: postgres:17.5-alpine + restart: unless-stopped + environment: + POSTGRES_DB: acidslide + POSTGRES_USER: acidslide + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U acidslide -d acidslide"] + interval: 5s + timeout: 5s + retries: 12 + networks: [private] + security_opt: [no-new-privileges:true] + + api: + build: + context: . + additional_contexts: + schemas: ../schemas + target: api + image: acidslide/service-api:${SERVICE_VERSION:-1.0.0} + restart: unless-stopped + environment: &service-environment + ACIDSLIDE_APP_ENV: production + ACIDSLIDE_DATABASE_URL: postgresql+psycopg://acidslide:${POSTGRES_PASSWORD}@postgres/acidslide + ACIDSLIDE_STORAGE_PATH: /data + ACIDSLIDE_PUBLIC_BASE_URL: https://${SITE_DOMAIN:-acidslide.dev} + ACIDSLIDE_ADMIN_API_KEY: ${ADMIN_API_KEY:?set ADMIN_API_KEY} + ACIDSLIDE_API_KEY_PEPPER: ${API_KEY_PEPPER:?set API_KEY_PEPPER} + ACIDSLIDE_ENCRYPTION_KEY: ${ENCRYPTION_KEY:?set ENCRYPTION_KEY} + ACIDSLIDE_TRUSTED_HOSTS: ${SITE_DOMAIN:-acidslide.dev},${API_DOMAIN:-api.acidslide.dev},localhost + ACIDSLIDE_GRADER_IMAGE: ${GRADER_IMAGE:-acidslide/grader:1.0.0} + ACIDSLIDE_GRADER_IMAGE_DIGEST: ${GRADER_IMAGE_DIGEST:?pin GRADER_IMAGE_DIGEST} + ACIDSLIDE_LIBREOFFICE_VERSION: ${LIBREOFFICE_VERSION:?set LIBREOFFICE_VERSION} + ACIDSLIDE_FONT_BUNDLE_HASH: ${FONT_BUNDLE_HASH:?set FONT_BUNDLE_HASH} + ACIDSLIDE_ASSET_MANIFEST_HASH: ${ASSET_MANIFEST_HASH:?set ASSET_MANIFEST_HASH} + ACIDSLIDE_ACTIVE_SCORING_MANIFEST_SHA256: ${ACTIVE_SCORING_MANIFEST_SHA256:?set ACTIVE_SCORING_MANIFEST_SHA256} + ACIDSLIDE_ACTIVE_GRADER_SOURCE_TREE_SHA256: ${ACTIVE_GRADER_SOURCE_TREE_SHA256:?set ACTIVE_GRADER_SOURCE_TREE_SHA256} + ACIDSLIDE_ACTIVE_ENVIRONMENT_ATTESTATION_SHA256: ${ACTIVE_ENVIRONMENT_ATTESTATION_SHA256:?set ACTIVE_ENVIRONMENT_ATTESTATION_SHA256} + ACIDSLIDE_ENVIRONMENT_ATTESTATION_JSON: ${ENVIRONMENT_ATTESTATION_JSON:?set ENVIRONMENT_ATTESTATION_JSON} + ACIDSLIDE_ACTIVE_GRADER_PACKAGE_SHA256: ${ACTIVE_GRADER_PACKAGE_SHA256:?set ACTIVE_GRADER_PACKAGE_SHA256} + ACIDSLIDE_ACTIVE_PROMPT_BUNDLE_SHA256: ${ACTIVE_PROMPT_BUNDLE_SHA256:?set ACTIVE_PROMPT_BUNDLE_SHA256} + ACIDSLIDE_ACTIVE_SCORED_ASSERTION_INVENTORY_SHA256: ${ACTIVE_SCORED_ASSERTION_INVENTORY_SHA256:?set ACTIVE_SCORED_ASSERTION_INVENTORY_SHA256} + ACIDSLIDE_ACTIVE_CHECKLIST_BUNDLE_SHA256: ${ACTIVE_CHECKLIST_BUNDLE_SHA256:?set ACTIVE_CHECKLIST_BUNDLE_SHA256} + ACIDSLIDE_ACTIVE_QUARANTINE_PROFILE_SHA256: ${ACTIVE_QUARANTINE_PROFILE_SHA256:?set ACTIVE_QUARANTINE_PROFILE_SHA256} + ACIDSLIDE_ACTIVE_MCE_PROFILE_SHA256: ${ACTIVE_MCE_PROFILE_SHA256:?set ACTIVE_MCE_PROFILE_SHA256} + ACIDSLIDE_ACTIVE_SCHEMA_BUNDLE_SHA256: ${ACTIVE_SCHEMA_BUNDLE_SHA256:?set ACTIVE_SCHEMA_BUNDLE_SHA256} + ACIDSLIDE_ACTIVE_SCHEMA_ROOT_MAP_SHA256: ${ACTIVE_SCHEMA_ROOT_MAP_SHA256:?set ACTIVE_SCHEMA_ROOT_MAP_SHA256} + ACIDSLIDE_ACTIVE_CANONICAL_PACKAGE_HASH_PROFILE_SHA256: ${ACTIVE_CANONICAL_PACKAGE_HASH_PROFILE_SHA256:?set ACTIVE_CANONICAL_PACKAGE_HASH_PROFILE_SHA256} + ACIDSLIDE_ACTIVE_GOLD_BYTE_SHA256: ${ACTIVE_GOLD_BYTE_SHA256:?set ACTIVE_GOLD_BYTE_SHA256} + ACIDSLIDE_ACTIVE_GOLD_MCE_RESOLVED_PACKAGE_SHA256: ${ACTIVE_GOLD_MCE_RESOLVED_PACKAGE_SHA256:?set ACTIVE_GOLD_MCE_RESOLVED_PACKAGE_SHA256} + ACIDSLIDE_ACTIVE_GOLD_CANONICAL_PACKAGE_SHA256: ${ACTIVE_GOLD_CANONICAL_PACKAGE_SHA256:?set ACTIVE_GOLD_CANONICAL_PACKAGE_SHA256} + ACIDSLIDE_SCORING_MANIFEST_PATH: /opt/acidslide/benchmark/scoring-manifest.json + ACIDSLIDE_GOLD_EVIDENCE_PATH: /opt/acidslide/benchmark/gold-evidence.json + ACIDSLIDE_GOLD_RESOLVED_PATH: /opt/acidslide/benchmark/deck/gold/acidslide-v1-gold.mce-resolved.pptx + ACIDSLIDE_CONTROL_HANDOFF_SCHEMA_PATH: /opt/acidslide/schemas/control-handoff.schema.json + ACIDSLIDE_CONTROL_VERIFICATION_KEYS_JSON: ${CONTROL_VERIFICATION_KEYS_JSON:?set CONTROL_VERIFICATION_KEYS_JSON} + ACIDSLIDE_DRIFT_CANARY_MAX_AGE_SECONDS: ${DRIFT_CANARY_MAX_AGE_SECONDS:-691200} + ACIDSLIDE_QUARANTINE_IMAGE: ${QUARANTINE_IMAGE:-acidslide/quarantine:1.0.0} + ACIDSLIDE_QUARANTINE_IMAGE_DIGEST: ${QUARANTINE_IMAGE_DIGEST:?pin QUARANTINE_IMAGE_DIGEST} + ACIDSLIDE_QUARANTINE_VERIFICATION_KEYS_JSON: ${QUARANTINE_VERIFICATION_KEYS_JSON:?set QUARANTINE_VERIFICATION_KEYS_JSON} + ACIDSLIDE_METRICS_BEARER_TOKEN: ${METRICS_BEARER_TOKEN:?set METRICS_BEARER_TOKEN} + volumes: + - private-storage:/data + - ../benchmark/scoring-manifest.json:/opt/acidslide/benchmark/scoring-manifest.json:ro + - ../benchmark/gold-evidence.json:/opt/acidslide/benchmark/gold-evidence.json:ro + - ../benchmark/deck/gold/acidslide-v1-gold.mce-resolved.pptx:/opt/acidslide/benchmark/deck/gold/acidslide-v1-gold.mce-resolved.pptx:ro + depends_on: + postgres: + condition: service_healthy + networks: [private, edge] + read_only: true + tmpfs: + - /tmp:size=64m,mode=1777 + cap_drop: [ALL] + security_opt: [no-new-privileges:true] + + worker: + build: + context: . + additional_contexts: + schemas: ../schemas + target: worker + image: acidslide/service-worker:${SERVICE_VERSION:-1.0.0} + command: ["acidslide-worker"] + restart: unless-stopped + environment: *service-environment + volumes: + - private-storage:/data + - ../benchmark/scoring-manifest.json:/opt/acidslide/benchmark/scoring-manifest.json:ro + - ../benchmark/gold-evidence.json:/opt/acidslide/benchmark/gold-evidence.json:ro + - ../benchmark/deck/gold/acidslide-v1-gold.mce-resolved.pptx:/opt/acidslide/benchmark/deck/gold/acidslide-v1-gold.mce-resolved.pptx:ro + - /var/run/docker.sock:/var/run/docker.sock + group_add: + - ${DOCKER_GID:?set DOCKER_GID} + depends_on: + api: + condition: service_healthy + networks: [private, outbound] + read_only: true + tmpfs: + - /tmp:size=64m,mode=1777 + cap_drop: [ALL] + security_opt: [no-new-privileges:true] + + quarantine: + build: + context: . + additional_contexts: + schemas: ../schemas + target: worker + image: acidslide/service-worker:${SERVICE_VERSION:-1.0.0} + command: ["acidslide-quarantine-worker"] + restart: unless-stopped + environment: + <<: *service-environment + ACIDSLIDE_QUARANTINE_SIGNING_KEY_ID: ${QUARANTINE_SIGNING_KEY_ID:?set QUARANTINE_SIGNING_KEY_ID} + ACIDSLIDE_QUARANTINE_SIGNING_PRIVATE_KEY: ${QUARANTINE_SIGNING_PRIVATE_KEY:?set QUARANTINE_SIGNING_PRIVATE_KEY} + volumes: + - private-storage:/data + - /var/run/docker.sock:/var/run/docker.sock + group_add: + - ${DOCKER_GID:?set DOCKER_GID} + depends_on: + api: + condition: service_healthy + networks: [private] + read_only: true + tmpfs: + - /tmp:size=64m,mode=1777 + cap_drop: [ALL] + security_opt: [no-new-privileges:true] + + caddy: + image: caddy:2.10.0-alpine + restart: unless-stopped + environment: + SITE_DOMAIN: ${SITE_DOMAIN:-acidslide.dev} + API_DOMAIN: ${API_DOMAIN:-api.acidslide.dev} + TLS_EMAIL: ${TLS_EMAIL:?set TLS_EMAIL} + ports: + - "80:80" + - "443:443" + - "443:443/udp" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy-data:/data + - caddy-config:/config + depends_on: [api] + networks: [edge] + cap_drop: [ALL] + cap_add: [NET_BIND_SERVICE] + security_opt: [no-new-privileges:true] + +networks: + edge: + private: + internal: true + outbound: + +volumes: + postgres-data: + private-storage: + caddy-data: + caddy-config: diff --git a/acidslide-v1/service/pyproject.toml b/acidslide-v1/service/pyproject.toml new file mode 100644 index 0000000..2b8e1df --- /dev/null +++ b/acidslide-v1/service/pyproject.toml @@ -0,0 +1,71 @@ +[build-system] +requires = ["hatchling>=1.27"] +build-backend = "hatchling.build" + +[project] +name = "acidslide-service" +version = "1.0.0a1" +description = "Hosted, grading-verified AcidSlide leaderboard service" +readme = "README.md" +requires-python = ">=3.12,<3.15" +license = "Apache-2.0" +dependencies = [ + "alembic>=1.16,<2", + "cryptography>=48.0.1,<49", + "fastapi>=0.116,<1", + "jinja2>=3.1.6,<4", + "jsonschema>=4.25,<5", + "prometheus-client>=0.22,<1", + "psycopg[binary]>=3.2.9,<4", + "pydantic-settings>=2.10,<3", + "python-multipart>=0.0.20,<1", + "rfc8785>=0.1.4,<1", + "sqlalchemy>=2.0.41,<3", + "uvicorn[standard]>=0.35,<1", +] + +[project.optional-dependencies] +dev = [ + "httpx>=0.28,<1", + "lxml>=6.1,<7", + "lxml-stubs>=0.5.1,<1", + "mypy>=1.17,<2", + "pip-audit>=2.10,<3", + "playwright>=1.55,<2", + "pytest>=9.0.3,<10", + "pytest-cov>=6.2,<7", + "ruff>=0.12,<1", + "types-PyYAML>=6.0.12,<7", + "types-jsonschema>=4.25,<5", +] + +[project.scripts] +acidslide-service = "acidslide_service.main:run" +acidslide-worker = "acidslide_service.worker:run" +acidslide-quarantine-worker = "acidslide_service.quarantine_worker:run" +acidslide-admin = "acidslide_service.cli:main" + +[tool.hatch.build.targets.wheel] +packages = ["acidslide_service"] + +[tool.ruff] +target-version = "py312" +line-length = 100 + +[tool.ruff.lint] +select = ["E", "F", "I", "N", "W", "UP", "B", "SIM", "RUF"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "--strict-markers --strict-config" +pythonpath = ["../grader"] + +[tool.coverage.run] +branch = true +source = ["acidslide_service"] + +[tool.mypy] +python_version = "3.12" +strict = true +plugins = ["pydantic.mypy"] +mypy_path = "../grader" diff --git a/acidslide-v1/service/tests/__init__.py b/acidslide-v1/service/tests/__init__.py new file mode 100644 index 0000000..a4dae3a --- /dev/null +++ b/acidslide-v1/service/tests/__init__.py @@ -0,0 +1 @@ +"""Hosted service tests.""" diff --git a/acidslide-v1/service/tests/conftest.py b/acidslide-v1/service/tests/conftest.py new file mode 100644 index 0000000..f9a81f8 --- /dev/null +++ b/acidslide-v1/service/tests/conftest.py @@ -0,0 +1,434 @@ +from __future__ import annotations + +import io +import json +import uuid +import zipfile +from collections.abc import Iterator +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Any, cast + +import pytest +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from fastapi.testclient import TestClient +from httpx import Response +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.config import Settings +from acidslide_service.database import Base, create_db_engine +from acidslide_service.main import create_app +from acidslide_service.quarantine_handoff import encode_private_key, encode_public_key, utc_text +from acidslide_service.quarantine_job import normative_profile_hashes +from acidslide_service.quarantine_runner import InsecureInProcessQuarantineRunner +from acidslide_service.quarantine_worker import quarantine_once +from acidslide_service.runner import HostedArtifactBinding + +MANIFEST_HASH = f"sha256:{'a' * 64}" +GRADER_SOURCE_HASH = f"sha256:{'b' * 64}" +ENVIRONMENT_HASH = "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" + + +def hosted_artifact_binding( + submission_id: str = "00000000-0000-0000-0000-000000000001", +) -> HostedArtifactBinding: + return HostedArtifactBinding( + prompt_variant="canonical", + generation_seed=None, + schema_validation_performed=True, + schema_valid=True, + schema_violations=(), + schema_bundle_sha256=f"sha256:{'5' * 64}", + schema_root_map_sha256=f"sha256:{'6' * 64}", + mce_profile_sha256=f"sha256:{'4' * 64}", + canonical_package_hash_profile_sha256=f"sha256:{'7' * 64}", + canonical_package_hash_v1=f"sha256:{'d' * 64}", + gold_duplicate_check="clear", + submission_sha256=f"sha256:{'e' * 64}", + mce_resolved_package_sha256=f"sha256:{'f' * 64}", + assistance_class="unassisted", + generation_profile_sha256=f"sha256:{'a' * 64}", + attested_metrics={"generation_strategy": "direct"}, + attestation={"human_intervention": False}, + submission_id=submission_id, + campaign_id="00000000-0000-0000-0000-000000000002", + robustness_group_id=None, + campaign_slot=1, + submitter_id="00000000-0000-0000-0000-000000000003", + model_key="00000000-0000-0000-0000-000000000004", + model_revision_key="00000000-0000-0000-0000-000000000005", + ) + + +@pytest.fixture +def settings(tmp_path: Path) -> Settings: + signing_key = Ed25519PrivateKey.generate() + key_id = "test-quarantine-key" + now = datetime.now(UTC) + runtime_settings = Settings( + database_url=f"sqlite:///{tmp_path / 'service.db'}", + storage_path=tmp_path / "data", + admin_api_key="test-admin-key", + api_key_pepper="test-pepper", + submissions_per_hour=100, + free_monthly_quota=100, + trusted_hosts=["testserver"], + active_scoring_manifest_sha256=MANIFEST_HASH, + active_grader_source_tree_sha256=GRADER_SOURCE_HASH, + active_environment_attestation_sha256=ENVIRONMENT_HASH, + allow_insecure_quarantine_runner=True, + quarantine_signing_key_id=key_id, + quarantine_signing_private_key=encode_private_key(signing_key), + quarantine_verification_keys_json=json.dumps( + { + key_id: { + "public_key": encode_public_key(signing_key.public_key()), + "not_before": utc_text(now - timedelta(days=1)), + "not_after": utc_text(now + timedelta(days=1)), + "revoked_at": None, + } + } + ), + ) + profiles = normative_profile_hashes(runtime_settings) + runtime_settings.active_quarantine_profile_sha256 = profiles["quarantine_profile_sha256"] + runtime_settings.active_mce_profile_sha256 = profiles["mce_profile_sha256"] + runtime_settings.active_schema_bundle_sha256 = profiles["schema_bundle_sha256"] + runtime_settings.active_schema_root_map_sha256 = profiles["schema_root_map_sha256"] + runtime_settings.active_canonical_package_hash_profile_sha256 = profiles[ + "canonical_package_hash_profile_sha256" + ] + return runtime_settings + + +@pytest.fixture +def sessions(settings: Settings) -> Iterator[sessionmaker[Session]]: + engine = create_db_engine(settings) + Base.metadata.create_all(engine) + factory = sessionmaker(bind=engine, expire_on_commit=False, autoflush=False) + yield factory + engine.dispose() + + +@pytest.fixture +def client( + settings: Settings, + sessions: sessionmaker[Session], +) -> Iterator[TestClient]: + app = create_app(settings, sessions) + app.state.test_settings = settings + app.state.test_sessions = sessions + with TestClient(app) as test_client: + yield test_client + + +def make_pptx( + slide_count: int = 5, + *, + external_relationship: bool = False, + embedded_spreadsheet: bool = False, + nested_archive: bool = False, + ole: bool = False, + traversal: bool = False, +) -> bytes: + result = io.BytesIO() + with zipfile.ZipFile(result, "w", compression=zipfile.ZIP_DEFLATED) as archive: + archive.writestr( + "[Content_Types].xml", + '' + '' + '' + + ( + '' + if embedded_spreadsheet + else "" + ) + + '' + + "".join( + f'' + for slide in range(1, slide_count + 1) + ) + + "", + ) + archive.writestr( + "ppt/presentation.xml", + """ + + """ + + "".join( + f'' + for slide in range(1, slide_count + 1) + ) + + """ + + + """, + ) + archive.writestr( + "_rels/.rels", + '' + '' + '', + ) + for slide in range(1, slide_count + 1): + archive.writestr( + f"ppt/slides/slide{slide}.xml", + """ + + + + + + """, + ) + slide_relationships = "".join( + f'' + for slide in range(1, slide_count + 1) + ) + external = ( + '' + if external_relationship + else "" + ) + archive.writestr( + "ppt/_rels/presentation.xml.rels", + '' + + slide_relationships + + external + + "", + ) + if nested_archive: + archive.writestr("ppt/media/payload.zip", b"PK\x03\x04payload") + if embedded_spreadsheet: + workbook_bytes = io.BytesIO() + with zipfile.ZipFile(workbook_bytes, "w", compression=zipfile.ZIP_DEFLATED) as workbook: + workbook.writestr( + "[Content_Types].xml", + '' + '' + '' + '' + "", + ) + workbook.writestr( + "xl/workbook.xml", + '' + '', + ) + workbook.writestr( + "_rels/.rels", + '' + '', + ) + archive.writestr("ppt/embeddings/chart-data.xlsx", workbook_bytes.getvalue()) + if ole: + archive.writestr( + "ppt/media/picture.png", bytes.fromhex("D0CF11E0A1B11AE1") + b"payload" + ) + if traversal: + archive.writestr("../escape.xml", "unsafe") + return result.getvalue() + + +def metadata(campaign_id: str = "auto", **overrides: Any) -> dict[str, Any]: + value: dict[str, Any] = { + "campaign_id": campaign_id, + "generation_seed": None, + "efficiency_metrics": {"generation_strategy": "direct"}, + "attestation": { + "method": "Single API generation pass", + "human_intervention": False, + "post_processing": False, + "external_resources_used": False, + }, + } + value.update(overrides) + return value + + +def create_org(client: TestClient, name: str = "Test Lab", quota: int = 100) -> tuple[str, str]: + response = client.post( + "/v1/admin/organizations", + headers={"X-Admin-Key": "test-admin-key"}, + json={"name": name, "monthly_quota": quota}, + ) + assert response.status_code == 201, response.text + payload = response.json() + return payload["organization_id"], payload["api_key"] + + +def create_model_revision( + client: TestClient, + api_key: str, + *, + display_name: str = "Model Alpha", + display_version: str | None = None, + owner_attribution: str = "submitter-attested", +) -> tuple[str, str]: + headers = {"X-API-Key": api_key} + model = client.post( + "/v1/models", + headers=headers, + json={"display_name": display_name, "owner_attribution": owner_attribution}, + ) + assert model.status_code == 201, model.text + model_key = model.json()["model_key"] + revision = client.post( + f"/v1/models/{model_key}/revisions", + headers=headers, + json={ + "display_version": display_version or f"test-{uuid.uuid4()}", + "revision_note": "Test fixture revision", + }, + ) + assert revision.status_code == 201, revision.text + return model_key, revision.json()["model_revision_key"] + + +def generation_profile( + revision_key: str, + *, + human_intervention_permitted: bool = False, +) -> dict[str, Any]: + return { + "schema_version": "1.0", + "profile_id": "acidslide-generation-profile-v1", + "canonicalization": "RFC8785-JCS", + "generator": { + "provider": "test-provider", + "model_identifier": "test-model", + "immutable_revision": revision_key, + "api_surface": "test-api", + }, + "generation_strategy": "direct", + "toolchain": [], + "sampling": { + "temperature": 0, + "top_p": 1, + "top_k": None, + "max_output_tokens": 4096, + "other_parameters": [], + }, + "permissions": { + "human_intervention_permitted": human_intervention_permitted, + "post_processing_permitted": False, + }, + } + + +def register_generation_profile( + client: TestClient, + api_key: str, + revision_key: str, + *, + human_intervention_permitted: bool = False, +) -> str: + response = client.post( + "/v1/generation-profiles", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "profile": generation_profile( + revision_key, + human_intervention_permitted=human_intervention_permitted, + ), + }, + ) + assert response.status_code == 201, response.text + digest = response.json()["generation_profile_sha256"] + assert isinstance(digest, str) + return digest + + +def create_campaign( + client: TestClient, + api_key: str, + *, + tier: int = 1, + prompt_variant: str = "canonical", + revision_key: str | None = None, + assistance_class: str = "unassisted", +) -> str: + if revision_key is None: + _, revision_key = create_model_revision(client, api_key) + cohort = client.get("/v1/versions").json()["active_scoring_cohort_id"] + profile_sha256 = register_generation_profile( + client, + api_key, + revision_key, + human_intervention_permitted=assistance_class == "human-assisted", + ) + response = client.post( + "/v1/campaigns", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": cohort, + "tier": tier, + "prompt_variant": prompt_variant, + "assistance_class": assistance_class, + "generation_profile_sha256": profile_sha256, + }, + ) + assert response.status_code == 201, response.text + campaign_id = response.json()["campaign_id"] + assert isinstance(campaign_id, str) + return campaign_id + + +def submit( + client: TestClient, + api_key: str, + *, + deck: bytes | None = None, + submission_metadata: dict[str, Any] | None = None, +) -> Response: + outgoing = dict(submission_metadata or metadata()) + if outgoing.get("campaign_id") == "auto": + outgoing["campaign_id"] = create_campaign(client, api_key) + response = cast( + Response, + client.post( + "/v1/submissions", + headers={"Authorization": f"Bearer {api_key}"}, + files={ + "metadata": ( + None, + json.dumps(outgoing), + "application/json", + ), + "file": ( + "submission.pptx", + deck or make_pptx(), + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + ), + }, + ), + ) + if response.status_code == 202: + app_state = cast(Any, client.app).state + test_settings = cast(Settings, app_state.test_settings) + test_sessions = cast(sessionmaker[Session], app_state.test_sessions) + quarantine_once( + test_settings, + test_sessions, + InsecureInProcessQuarantineRunner(test_settings), + "test-quarantine-worker", + ) + return response diff --git a/acidslide-v1/service/tests/test_api.py b/acidslide-v1/service/tests/test_api.py new file mode 100644 index 0000000..12a6943 --- /dev/null +++ b/acidslide-v1/service/tests/test_api.py @@ -0,0 +1,377 @@ +from __future__ import annotations + +import hashlib +from datetime import UTC, datetime, timedelta +from pathlib import Path + +import rfc8785 +import yaml +from fastapi.testclient import TestClient +from sqlalchemy import func, select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.config import Settings +from acidslide_service.main import create_app +from acidslide_service.models import DriftCanaryRun, Submission, WorkerHeartbeat +from acidslide_service.quarantine_handoff import utc_text +from acidslide_service.service import scoring_cohort_id + +from .conftest import ( + create_campaign, + create_model_revision, + create_org, + generation_profile, + make_pptx, + metadata, + register_generation_profile, + submit, +) + + +def add_passing_canary( + session: Session, + settings: Settings, + *, + completed_at: datetime | None = None, +) -> DriftCanaryRun: + moment = (completed_at or datetime.now(UTC)).astimezone(UTC) + run_id = "00000000-0000-0000-0000-000000000099" + cohort_id = scoring_cohort_id( + settings.active_scoring_manifest_sha256, + settings.active_grader_source_tree_sha256, + settings.active_environment_attestation_sha256, + ) + evidence = { + "schema_version": "1.0", + "canary_run_id": run_id, + "benchmark_version": settings.active_benchmark_versions[0], + "scoring_cohort_id": cohort_id, + "scoring_manifest_sha256": settings.active_scoring_manifest_sha256, + "gold_evidence_sha256": f"sha256:{'f' * 64}", + "status": "pass", + "started_at": utc_text(moment - timedelta(minutes=1)), + "completed_at": utc_text(moment), + "controls": [{"targeted_tier": tier} for tier in (1, 2, 3)], + "error": None, + } + record = DriftCanaryRun( + id=run_id, + benchmark_version=settings.active_benchmark_versions[0], + scoring_cohort_id=cohort_id, + scoring_manifest_sha256=settings.active_scoring_manifest_sha256, + status="pass", + evidence_json=evidence, + evidence_sha256=(f"sha256:{hashlib.sha256(rfc8785.dumps(evidence)).hexdigest()}"), + started_at=moment - timedelta(minutes=1), + completed_at=moment, + ) + session.add(record) + session.commit() + return record + + +def test_public_surface_and_security_headers(client: TestClient) -> None: + homepage = client.get("/") + assert homepage.status_code == 200 + assert "Can your model make" in homepage.text + assert homepage.headers["x-content-type-options"] == "nosniff" + assert "frame-ancestors 'none'" in homepage.headers["content-security-policy"] + assert client.get("/health/live").json() == {"status": "ok"} + assert client.get("/health/ready").json() == {"status": "ready"} + assert client.get("/v1/versions").json()["active"] == ["acidslide-v1.0.0"] + assert client.get("/v1/leaderboard").status_code == 200 + + +def test_admin_issues_key_once_and_auth_is_tenant_scoped(client: TestClient) -> None: + assert client.post("/v1/admin/organizations", json={"name": "No auth"}).status_code == 401 + _, first_key = create_org(client, "First") + _, second_key = create_org(client, "Second") + assert first_key.startswith("asv1_") + accepted = submit(client, first_key) + assert accepted.status_code == 202, accepted.text + submission_id = accepted.json()["submission_id"] + assert accepted.json()["status_url"] == f"/v1/submissions/{submission_id}" + + own = client.get( + f"/v1/submissions/{submission_id}", + headers={"X-API-Key": first_key}, + ) + assert own.status_code == 200 + assert own.json()["status"] == "queued" + assert ( + client.get( + f"/v1/submissions/{submission_id}", + headers={"X-API-Key": second_key}, + ).status_code + == 404 + ) + assert client.get(f"/v1/submissions/{submission_id}").status_code == 401 + + +def test_invalid_cohort_tier_and_quarantine_are_explicit(client: TestClient) -> None: + _, api_key = create_org(client) + _, revision_key = create_model_revision(client, api_key) + profile_sha256 = register_generation_profile(client, api_key, revision_key) + wrong_cohort = client.post( + "/v1/campaigns", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": f"sha256:{'0' * 64}", + "tier": 1, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert wrong_cohort.status_code == 422 + assert wrong_cohort.json()["detail"]["code"] == "invalid_scoring_cohort" + + wrong_tier = submit(client, api_key, deck=make_pptx(slide_count=4)) + assert wrong_tier.status_code == 202 + wrong_tier_status = client.get( + f"/v1/submissions/{wrong_tier.json()['submission_id']}", + headers={"X-API-Key": api_key}, + ).json() + assert wrong_tier_status["status"] == "rejected" + assert wrong_tier_status["error"]["code"] == "invalid_tier" + + malicious = submit(client, api_key, deck=make_pptx(external_relationship=True)) + assert malicious.status_code == 202 + malicious_status = client.get( + f"/v1/submissions/{malicious.json()['submission_id']}", + headers={"X-API-Key": api_key}, + ).json() + assert malicious_status["status"] == "rejected" + assert malicious_status["error"]["code"] == "quarantine_rejected" + assert "External OOXML" in malicious_status["error"]["message"] + + +def test_generation_profiles_are_server_hashed_immutable_and_scope_bound( + client: TestClient, +) -> None: + _, owner_key = create_org(client, "Profile owner") + _, stranger_key = create_org(client, "Profile stranger") + _, revision_key = create_model_revision(client, owner_key) + payload = generation_profile(revision_key) + request = {"model_revision_key": revision_key, "profile": payload} + first = client.post( + "/v1/generation-profiles", + headers={"X-API-Key": owner_key}, + json=request, + ) + replay = client.post( + "/v1/generation-profiles", + headers={"X-API-Key": owner_key}, + json=request, + ) + assert first.status_code == replay.status_code == 201 + expected = f"sha256:{hashlib.sha256(rfc8785.dumps(payload)).hexdigest()}" + assert first.json()["generation_profile_sha256"] == expected + assert replay.json() == first.json() + + invalid_payload = dict(payload) + invalid_payload["unpublished_extension"] = True + invalid = client.post( + "/v1/generation-profiles", + headers={"X-API-Key": owner_key}, + json={"model_revision_key": revision_key, "profile": invalid_payload}, + ) + assert invalid.status_code == 422 + assert invalid.json()["detail"]["code"] == "invalid_generation_profile" + + _, other_revision = create_model_revision(client, owner_key, display_name="Other revision") + cohort = client.get("/v1/versions").json()["active_scoring_cohort_id"] + wrong_revision = client.post( + "/v1/campaigns", + headers={"X-API-Key": owner_key}, + json={ + "model_revision_key": other_revision, + "scoring_cohort_id": cohort, + "tier": 1, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": expected, + }, + ) + assert wrong_revision.status_code == 422 + assert wrong_revision.json()["detail"]["code"] == "invalid_generation_profile" + + _, stranger_revision = create_model_revision(client, stranger_key) + conflicting_registration = client.post( + "/v1/generation-profiles", + headers={"X-API-Key": stranger_key}, + json={"model_revision_key": stranger_revision, "profile": payload}, + ) + assert conflicting_registration.status_code == 409 + assert conflicting_registration.json()["detail"]["code"] == ( + "generation_profile_scope_conflict" + ) + cross_tenant = client.post( + "/v1/campaigns", + headers={"X-API-Key": stranger_key}, + json={ + "model_revision_key": stranger_revision, + "scoring_cohort_id": cohort, + "tier": 1, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": expected, + }, + ) + assert cross_tenant.status_code == 422 + assert cross_tenant.json()["detail"]["code"] == "invalid_generation_profile" + + +def test_unassisted_campaign_rejects_intervention_permitted_profile( + client: TestClient, +) -> None: + _, api_key = create_org(client) + _, revision_key = create_model_revision(client, api_key) + profile_sha256 = register_generation_profile( + client, + api_key, + revision_key, + human_intervention_permitted=True, + ) + response = client.post( + "/v1/campaigns", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": client.get("/v1/versions").json()["active_scoring_cohort_id"], + "tier": 1, + "prompt_variant": "canonical", + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert response.status_code == 422 + assert response.json()["detail"]["code"] == "invalid_assistance_class" + + +def test_tuple_rate_limit_has_retry_after(client: TestClient) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + slots = [] + for _ in range(3): + accepted = submit(client, api_key, submission_metadata=metadata(campaign_id)) + assert accepted.status_code == 202 + slots.append(accepted.json()["campaign_slot"]) + assert slots == [1, 2, 3] + limited = submit(client, api_key, submission_metadata=metadata(campaign_id)) + assert limited.status_code == 429 + assert int(limited.headers["Retry-After"]) > 0 + assert limited.json()["detail"]["code"] == "rate_limited" + + +def test_metadata_conditional_fields_are_enforced(client: TestClient) -> None: + _, api_key = create_org(client) + invalid = metadata() + invalid["attestation"]["external_resources_used"] = True + response = submit(client, api_key, submission_metadata=invalid) + assert response.status_code == 422 + assert response.json()["detail"]["code"] == "invalid_metadata" + + +def test_repeated_malicious_uploads_suspend_account(client: TestClient) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + for attempt in range(5): + response = submit(client, api_key, deck=make_pptx(nested_archive=True)) + assert response.status_code == 202 + if attempt == 0: + rejected = client.get( + f"/v1/submissions/{response.json()['submission_id']}", + headers={"X-API-Key": api_key}, + ).json() + assert rejected["error"]["code"] == "quarantine_rejected" + suspended = submit( + client, + api_key, + submission_metadata=metadata(campaign_id), + ) + assert suspended.status_code == 403 + assert suspended.json()["detail"]["code"] == "account_suspended" + + +def test_reviewed_openapi_covers_runtime_contract(client: TestClient) -> None: + reviewed_path = Path(__file__).parents[1] / "api-spec.yaml" + reviewed = yaml.safe_load(reviewed_path.read_text()) + runtime = client.get("/v1/openapi.json").json() + reviewed_paths = {f"/v1{path}" for path in reviewed["paths"]} + runtime_contract_paths = {path for path in runtime["paths"] if path.startswith("/v1/")} + assert runtime_contract_paths <= reviewed_paths + assert reviewed["openapi"] == "3.1.0" + + +def test_metrics_can_be_bearer_protected(client: TestClient) -> None: + response = client.get("/metrics") + assert response.status_code == 200 + assert "acidslide_http_requests_total" in response.text + + +def test_production_readiness_requires_both_worker_roles_and_metrics_token( + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + production = settings.model_copy( + update={ + "app_env": "production", + "metrics_bearer_token": "metrics-secret", + } + ) + with TestClient(create_app(production, sessions)) as production_client: + missing = production_client.get("/health/ready") + assert missing.status_code == 503 + assert missing.json()["detail"]["code"] == "worker_unavailable" + assert "grading, quarantine" in missing.json()["detail"]["message"] + assert production_client.get("/metrics").status_code == 401 + assert ( + production_client.get( + "/metrics", headers={"Authorization": "Bearer metrics-secret"} + ).status_code + == 200 + ) + + with sessions() as session: + for role in ("grading", "quarantine"): + session.add( + WorkerHeartbeat( + worker_id=f"{role}:test", + hostname="test", + process_id=1, + last_seen_at=datetime.now(UTC), + ) + ) + session.commit() + missing_canary = production_client.get("/health/ready") + assert missing_canary.status_code == 503 + assert missing_canary.json()["detail"]["code"] == "drift_canary_missing" + with sessions() as session: + add_passing_canary(session, production) + assert production_client.get("/health/ready").json() == {"status": "ready"} + metrics = production_client.get( + "/metrics", headers={"Authorization": "Bearer metrics-secret"} + ) + assert "acidslide_drift_canary_blocked 0.0" in metrics.text + + +def test_production_submission_is_blocked_without_a_current_canary( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client, "Canary blocked submitter") + campaign_id = create_campaign(client, api_key) + production = settings.model_copy(update={"app_env": "production"}) + with TestClient(create_app(production, sessions)) as production_client: + blocked = submit( + production_client, + api_key, + submission_metadata=metadata(campaign_id), + ) + assert blocked.status_code == 503 + assert blocked.json()["detail"]["code"] == "drift_canary_missing" + with sessions() as session: + assert session.scalar(select(func.count(Submission.id))) == 0 diff --git a/acidslide-v1/service/tests/test_campaign_contract.py b/acidslide-v1/service/tests/test_campaign_contract.py new file mode 100644 index 0000000..7c9878e --- /dev/null +++ b/acidslide-v1/service/tests/test_campaign_contract.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +from pathlib import Path + +from fastapi.testclient import TestClient +from sqlalchemy import func, select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.config import Settings +from acidslide_service.models import RobustnessGroup, Submission +from acidslide_service.runner import ( + GradeOutcome, + GradingError, + HostedArtifactBinding, + ScoringCohortBinding, +) +from acidslide_service.service import scoring_cohort_id +from acidslide_service.worker import worker_once + +from .conftest import ( + ENVIRONMENT_HASH, + GRADER_SOURCE_HASH, + MANIFEST_HASH, + create_campaign, + create_model_revision, + create_org, + metadata, + register_generation_profile, + submit, +) +from .test_worker_and_leaderboard import FakeRunner + + +class FailedBeforeReportRunner: + def grade( + self, + _path: Path, + _tier: int, + _submission_id: str, + _cohort: ScoringCohortBinding, + _artifact: HostedArtifactBinding, + ) -> GradeOutcome: + raise GradingError("no report exists") + + +def test_scoring_cohort_id_matches_frozen_jcs_vector() -> None: + assert ( + scoring_cohort_id(MANIFEST_HASH, GRADER_SOURCE_HASH, ENVIRONMENT_HASH) + == "sha256:959eb774fe23dfe05c4fcee347c079e1ede96d70a0dad6c97d05fff94b890bfa" + ) + + +def test_identity_and_campaign_keys_are_server_issued_and_tenant_scoped( + client: TestClient, +) -> None: + submitter_id, owner_key = create_org(client, "Identity owner") + _, stranger_key = create_org(client, "Identity stranger") + model_key, revision_key = create_model_revision( + client, + owner_key, + display_name="Attested model label", + display_version="provider-2026-07-18", + ) + cohort = client.get("/v1/versions").json()["active_scoring_cohort_id"] + profile_sha256 = register_generation_profile(client, owner_key, revision_key) + campaign = client.post( + "/v1/campaigns", + headers={"X-API-Key": owner_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": cohort, + "tier": 2, + "prompt_variant": "paraphrase-a", + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert campaign.status_code == 201, campaign.text + body = campaign.json() + assert body["submitter_id"] == submitter_id + assert body["model_key"] == model_key + assert body["model_revision_key"] == revision_key + assert body["benchmark_version"] == "acidslide-v1.0.0" + assert body["scoring_cohort_id"] == cohort + assert body["slot_count"] == 3 + assert body["occupied_slots"] == 0 + assert body["status"] == "open" + assert len(body["window_id"]) == 36 + + duplicate = client.post( + "/v1/campaigns", + headers={"X-API-Key": owner_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": cohort, + "tier": 2, + "prompt_variant": "paraphrase-a", + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert duplicate.status_code == 409 + assert duplicate.json()["detail"]["code"] == "campaign_window_exists" + public_campaign = client.get( + f"/v1/campaigns/{body['campaign_id']}", + headers={"X-API-Key": stranger_key}, + ) + assert public_campaign.status_code == 200 + assert public_campaign.json()["slots"] == [] + assert ( + client.post( + f"/v1/models/{model_key}/revisions", + headers={"X-API-Key": stranger_key}, + json={"display_version": "alias", "revision_note": "not owned"}, + ).status_code + == 404 + ) + + +def test_submission_cannot_override_campaign_binding(client: TestClient) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key, tier=2, prompt_variant="paraphrase-b") + attempted_override = metadata(campaign_id) + attempted_override.update( + { + "tier": 1, + "benchmark_version": "acidslide-v0.1.0", + "prompt_variant": "canonical", + "model_key": "free-text-alias", + } + ) + rejected = submit(client, api_key, submission_metadata=attempted_override) + assert rejected.status_code == 422 + assert rejected.json()["detail"]["code"] == "invalid_metadata" + + +def test_failed_job_releases_reserved_ordinal( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + first = submit(client, api_key, submission_metadata=metadata(campaign_id)) + assert first.json()["campaign_slot"] == 1 + assert worker_once(settings, sessions, FailedBeforeReportRunner(), "failed-worker") + + failed = client.get( + f"/v1/submissions/{first.json()['submission_id']}", + headers={"X-API-Key": api_key}, + ).json() + assert failed["status"] == "failed" + assert failed["campaign_slot"] is None + retry = submit(client, api_key, submission_metadata=metadata(campaign_id)) + assert retry.status_code == 202 + assert retry.json()["campaign_slot"] == 1 + + +def test_ineligible_report_occupies_slot_at_zero_and_public_ledger_is_append_only( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + outcomes = [FakeRunner(0.9, eligible=False), FakeRunner(0.9), FakeRunner(0.9)] + submission_ids: list[str] = [] + for runner in outcomes: + accepted = submit(client, api_key, submission_metadata=metadata(campaign_id)) + submission_ids.append(accepted.json()["submission_id"]) + assert worker_once(settings, sessions, runner, "worker") + + campaign = client.get(f"/v1/campaigns/{campaign_id}", headers={"X-API-Key": api_key}).json() + assert campaign["status"] == "completed" + assert campaign["occupied_slots"] == 3 + assert campaign["official_score"] == 0.6 + assert [slot["campaign_score"] for slot in campaign["slots"]] == [0.0, 0.9, 0.9] + assert campaign["verification_scope"] == "artifact_conformance" + assert campaign["verification_label"] == "grading-verified artifact score; generation-attested" + + ledger = client.get("/v1/leaderboard/runs").json() + rows = {row["submission_id"]: row for row in ledger["runs"]} + assert set(rows) == set(submission_ids) + first = rows[submission_ids[0]] + assert first["eligible"] is False + assert first["campaign_score"] == 0.0 + assert first["scoring_cohort_id"] == campaign["scoring_cohort_id"] + assert first["scoring_manifest_sha256"] == MANIFEST_HASH + assert first["grader_source_tree_sha256"] == GRADER_SOURCE_HASH + assert first["environment_attestation_sha256"] == ENVIRONMENT_HASH + assert "report_json" not in first + with sessions() as session: + persisted = session.scalar(select(Submission).where(Submission.id == submission_ids[0])) + assert persisted is not None + assert persisted.campaign_slot == 1 + assert persisted.run is not None + + +def test_robustness_group_creation_is_atomic_when_a_child_conflicts( + client: TestClient, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + _, revision_key = create_model_revision(client, api_key) + create_campaign(client, api_key, revision_key=revision_key, prompt_variant="canonical") + cohort = client.get("/v1/versions").json()["active_scoring_cohort_id"] + profile_sha256 = register_generation_profile(client, api_key, revision_key) + response = client.post( + "/v1/robustness-groups", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": cohort, + "tier": 1, + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert response.status_code == 409 + with sessions() as session: + assert session.scalar(select(func.count(RobustnessGroup.id))) == 0 diff --git a/acidslide-v1/service/tests/test_canary.py b/acidslide-v1/service/tests/test_canary.py new file mode 100644 index 0000000..9f60303 --- /dev/null +++ b/acidslide-v1/service/tests/test_canary.py @@ -0,0 +1,388 @@ +from __future__ import annotations + +import base64 +import hashlib +import json +import uuid +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Any + +import pytest +import rfc8785 +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from sqlalchemy import func, select, update +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.canary import ( + ControlAuthorizationError, + DriftCanaryError, + drift_canary_health, + load_frozen_canary_bindings, + run_drift_canary, +) +from acidslide_service.config import Settings +from acidslide_service.models import DriftCanaryAuthorizationUse, DriftCanaryRun +from acidslide_service.quarantine_handoff import encode_public_key, utc_text +from acidslide_service.runner import ( + CanaryGradeOutcome, + ReferenceControlBinding, + ScoringCohortBinding, +) +from acidslide_service.service import scoring_cohort_id + + +def _hash(label: str) -> str: + return f"sha256:{hashlib.sha256(label.encode()).hexdigest()}" + + +def _jcs_hash(value: Any) -> str: + return f"sha256:{hashlib.sha256(rfc8785.dumps(value)).hexdigest()}" + + +class FakeCanaryRunner: + def __init__( + self, + png_hashes: tuple[str, ...], + scene_graph_sha256: str, + score_hashes: dict[int, str], + *, + drift: str | None = None, + ) -> None: + self.png_hashes = png_hashes + self.scene_graph_sha256 = scene_graph_sha256 + self.score_hashes = score_hashes + self.drift = drift + self.calls: list[int] = [] + + def grade_reference_control( + self, + resolved_gold_path: Path, + tier: int, + cohort: ScoringCohortBinding, + control: ReferenceControlBinding, + ) -> CanaryGradeOutcome: + assert resolved_gold_path.is_file() + assert cohort.scoring_manifest_sha256.startswith("sha256:") + assert control.control_authorization_sha256.startswith("sha256:") + self.calls.append(tier) + if self.drift == "error" and tier == 2: + raise RuntimeError("controlled canary failure") + png_hashes = self.png_hashes + scene_hash = self.scene_graph_sha256 + score_hash = self.score_hashes[tier] + if self.drift == "png" and tier == 2: + png_hashes = (_hash("drifted-page"), *png_hashes[1:]) + if self.drift == "scene" and tier == 2: + scene_hash = _hash("drifted-scene") + if self.drift == "score" and tier == 2: + score_hash = _hash("drifted-score") + report = { + "run_kind": "reference_control", + "verification_label": ("grading-verified reference control; no generation attribution"), + "targeted_tier": tier, + "score_semantic_report_sha256": score_hash, + "fidelity_score": 1.0, + "deck_passed": True, + "eligible": False, + } + return CanaryGradeOutcome(report, png_hashes, scene_hash) + + +def _canary_fixture( + settings: Settings, + tmp_path: Path, +) -> tuple[list[dict[str, object]], tuple[str, ...], str, dict[int, str], datetime]: + now = datetime.now(UTC).replace(microsecond=0) + resolved_bytes = b"resolved-gold-control" + resolved_path = tmp_path / "gold-resolved.pptx" + resolved_path.write_bytes(resolved_bytes) + original_sha256 = _hash("original-gold") + resolved_sha256 = f"sha256:{hashlib.sha256(resolved_bytes).hexdigest()}" + canonical_sha256 = _hash("canonical-gold") + canonical_profile_sha256 = settings.active_canonical_package_hash_profile_sha256 + png_hashes = tuple(_hash(f"page-{page}") for page in range(1, 21)) + scene_hash = _hash("scene-graph") + score_hashes = {tier: _hash(f"score-tier-{tier}") for tier in (1, 2, 3)} + manifest = { + "benchmark_version": settings.active_benchmark_versions[0], + "gold": { + "original_byte_sha256": original_sha256, + "mce_resolved_package_sha256": resolved_sha256, + "mce_resolved_package_size_bytes": len(resolved_bytes), + "canonical_package_hash_profile_sha256": canonical_profile_sha256, + "canonical_package_hash_v1": canonical_sha256, + "scene_graph_sha256": scene_hash, + "canonical_png_sha256s": list(png_hashes), + }, + } + manifest_path = tmp_path / "scoring-manifest.json" + manifest_path.write_text(json.dumps(manifest), encoding="utf-8") + manifest_sha256 = _jcs_hash(manifest) + evidence = { + "evidence_id": "acidslide-gold-evidence-v1", + "benchmark_version": settings.active_benchmark_versions[0], + "scoring_manifest_sha256": manifest_sha256, + "scene_graph_sha256": scene_hash, + "profile_hashes": { + "canonical_package_hash_profile_sha256": canonical_profile_sha256, + }, + "reference_controls": [ + { + "targeted_tier": tier, + "score_semantic_report_sha256": score_hashes[tier], + } + for tier in (1, 2, 3) + ], + } + evidence_path = tmp_path / "gold-evidence.json" + evidence_path.write_text(json.dumps(evidence), encoding="utf-8") + evidence_sha256 = _jcs_hash(evidence) + + settings.scoring_manifest_path = manifest_path + settings.gold_evidence_path = evidence_path + settings.gold_resolved_path = resolved_path + settings.active_scoring_manifest_sha256 = manifest_sha256 + settings.active_gold_byte_sha256 = original_sha256 + settings.active_gold_mce_resolved_package_sha256 = resolved_sha256 + settings.active_gold_canonical_package_sha256 = canonical_sha256 + + signing_key = Ed25519PrivateKey.generate() + key_id = "drift-maintainer-key" + settings.control_verification_keys_json = json.dumps( + { + key_id: { + "public_key": encode_public_key(signing_key.public_key()), + "purposes": ["drift_canary"], + "not_before": utc_text(now - timedelta(days=1)), + "not_after": utc_text(now + timedelta(days=1)), + "revoked_at": None, + } + } + ) + cohort_id = scoring_cohort_id( + settings.active_scoring_manifest_sha256, + settings.active_grader_source_tree_sha256, + settings.active_environment_attestation_sha256, + ) + profile_hashes = { + "grader_source_tree_sha256": settings.active_grader_source_tree_sha256, + "environment_attestation_sha256": settings.active_environment_attestation_sha256, + "mce_profile_sha256": settings.active_mce_profile_sha256, + "xsd_bundle_sha256": settings.active_schema_bundle_sha256, + "schema_root_map_sha256": settings.active_schema_root_map_sha256, + "canonical_package_hash_profile_sha256": canonical_profile_sha256, + "scored_assertion_inventory_sha256": (settings.active_scored_assertion_inventory_sha256), + "checklist_bundle_sha256": settings.active_checklist_bundle_sha256, + } + authorizations: list[dict[str, object]] = [] + for tier in (1, 2, 3): + unsigned: dict[str, Any] = { + "schema_version": "1.0", + "authorization_id": str(uuid.uuid4()), + "canonicalization": "RFC8785-JCS", + "run_kind": "reference_control", + "purpose": "drift_canary", + "artifact_identity": { + "original_submission_sha256": original_sha256, + "mce_resolved_package_sha256": resolved_sha256, + "mce_resolved_package_size_bytes": len(resolved_bytes), + "canonical_package_hash_profile_sha256": canonical_profile_sha256, + "canonical_package_hash_v1": canonical_sha256, + }, + "evidence_binding": { + "evidence_id": evidence["evidence_id"], + "evidence_sha256": evidence_sha256, + }, + "scoring_manifest_sha256": manifest_sha256, + "scoring_cohort_id": cohort_id, + "profile_hashes": profile_hashes, + "requested_tier": tier, + "campaign_id": None, + "campaign_slot": None, + "submitter_id": None, + "model_key": None, + "model_revision_key": None, + "no_campaign_no_slot": True, + "duplicate_disposition": "allow_reference_only", + "issuer_key_id": key_id, + "issued_at": utc_text(now - timedelta(minutes=1)), + "expires_at": utc_text(now + timedelta(hours=1)), + "single_use_nonce": f"canary-tier-{tier}-{'n' * 32}", + } + signature = signing_key.sign(rfc8785.dumps(unsigned)) + authorizations.append( + unsigned + | { + "signature": { + "algorithm": "Ed25519", + "signature_base64": base64.b64encode(signature).decode(), + } + } + ) + return authorizations, png_hashes, scene_hash, score_hashes, now + + +def test_canary_pass_is_current_and_authorizations_are_single_use( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes) + with sessions() as session: + result = run_drift_canary(session, settings, runner, documents, now=now) + assert result.status == "pass" + assert runner.calls == [1, 2, 3] + assert drift_canary_health(session, settings).ready is True + assert session.scalar(select(func.count(DriftCanaryAuthorizationUse.authorization_id))) == 3 + with pytest.raises(ControlAuthorizationError, match="already been consumed"): + run_drift_canary(session, settings, runner, documents, now=now) + + +@pytest.mark.parametrize("drift", ["png", "scene", "score"]) +def test_canary_detects_every_normative_drift_surface( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, + drift: str, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes, drift=drift) + with sessions() as session: + result = run_drift_canary(session, settings, runner, documents, now=now) + assert result.status == "drift" + health = drift_canary_health(session, settings) + assert health.ready is False + assert health.code == "drift_canary_drift" + + +def test_tampered_authorization_fails_before_nonce_consumption( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + documents[0]["requested_tier"] = 2 + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes) + with sessions() as session: + with pytest.raises(ControlAuthorizationError, match="signature is invalid"): + run_drift_canary(session, settings, runner, documents, now=now) + assert session.scalar(select(func.count(DriftCanaryAuthorizationUse.authorization_id))) == 0 + + +@pytest.mark.parametrize( + ("key_case", "message"), + [ + ("missing", "No maintainer"), + ("shared", "must be distinct"), + ("unknown", "issuer key is unknown"), + ("purpose", "not scoped"), + ("public", "public key is missing"), + ("revoked", "key is revoked"), + ], +) +def test_control_key_scope_and_rotation_fail_closed( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, + key_case: str, + message: str, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + key_document = json.loads(settings.control_verification_keys_json) + key_id = next(iter(key_document)) + if key_case == "missing": + settings.control_verification_keys_json = "{}" + elif key_case == "shared": + settings.quarantine_verification_keys_json = settings.control_verification_keys_json + elif key_case == "unknown": + documents[0]["issuer_key_id"] = "unknown-maintainer-key" + elif key_case == "purpose": + key_document[key_id]["purposes"] = ["release_reference"] + settings.control_verification_keys_json = json.dumps(key_document) + elif key_case == "public": + key_document[key_id].pop("public_key") + settings.control_verification_keys_json = json.dumps(key_document) + else: + key_document[key_id]["revoked_at"] = utc_text(now - timedelta(seconds=30)) + settings.control_verification_keys_json = json.dumps(key_document) + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes) + with sessions() as session, pytest.raises(ControlAuthorizationError, match=message): + run_drift_canary(session, settings, runner, documents, now=now) + + +@pytest.mark.parametrize( + ("binding_case", "message"), + [ + ("manifest_digest", "manifest bytes"), + ("benchmark", "version is not active"), + ("active_gold", "active service state"), + ("gold_bytes", "Resolved gold bytes"), + ("scene", "scene graph"), + ("controls", "reference controls are missing"), + ], +) +def test_frozen_release_binding_mismatches_fail_closed( + settings: Settings, + tmp_path: Path, + binding_case: str, + message: str, +) -> None: + _canary_fixture(settings, tmp_path) + if binding_case == "manifest_digest": + settings.active_scoring_manifest_sha256 = _hash("wrong-manifest") + elif binding_case == "benchmark": + settings.active_benchmark_versions = ["acidslide-v2.0.0"] + elif binding_case == "active_gold": + settings.active_gold_byte_sha256 = _hash("wrong-gold") + elif binding_case == "gold_bytes": + settings.gold_resolved_path.write_bytes(b"tampered-gold") + else: + evidence = json.loads(settings.gold_evidence_path.read_text(encoding="utf-8")) + if binding_case == "scene": + evidence["scene_graph_sha256"] = _hash("wrong-scene") + else: + evidence.pop("reference_controls") + settings.gold_evidence_path.write_text(json.dumps(evidence), encoding="utf-8") + with pytest.raises(DriftCanaryError, match=message): + load_frozen_canary_bindings(settings) + + +def test_canary_runner_error_is_persisted_and_blocks_as_error( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes, drift="error") + with sessions() as session: + result = run_drift_canary(session, settings, runner, documents, now=now) + assert result.status == "error" + assert result.evidence_json["error"]["code"] == "canary_execution_failed" + assert drift_canary_health(session, settings).code == "drift_canary_error" + + +def test_missing_stale_and_tampered_evidence_fail_closed( + settings: Settings, + sessions: sessionmaker[Session], + tmp_path: Path, +) -> None: + documents, png_hashes, scene_hash, score_hashes, now = _canary_fixture(settings, tmp_path) + runner = FakeCanaryRunner(png_hashes, scene_hash, score_hashes) + with sessions() as session: + assert drift_canary_health(session, settings).code == "drift_canary_missing" + record = run_drift_canary(session, settings, runner, documents, now=now) + stale = drift_canary_health( + session, + settings, + now=record.completed_at + timedelta(seconds=settings.drift_canary_max_age_seconds + 1), + ) + assert stale.code == "drift_canary_stale" + session.execute( + update(DriftCanaryRun) + .where(DriftCanaryRun.id == record.id) + .values(evidence_json={"tampered": True}) + ) + session.commit() + assert drift_canary_health(session, settings).code == "drift_canary_tampered" diff --git a/acidslide-v1/service/tests/test_config.py b/acidslide-v1/service/tests/test_config.py new file mode 100644 index 0000000..5b4add1 --- /dev/null +++ b/acidslide-v1/service/tests/test_config.py @@ -0,0 +1,245 @@ +from __future__ import annotations + +import hashlib +import json +from datetime import UTC, datetime, timedelta +from typing import Any + +import pytest +import rfc8785 +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from pydantic import ValidationError + +from acidslide_service.config import Settings +from acidslide_service.quarantine_handoff import encode_public_key, utc_text + + +def _digest(seed: str) -> str: + return f"sha256:{hashlib.sha256(seed.encode()).hexdigest()}" + + +def _production_attestation( + *, + oci_image_digest: str, + grader_source_tree_sha256: str, + font_manifest_sha256: str, + schema_bundle_sha256: str, + schema_root_map_sha256: str, + mce_profile_sha256: str, + canonical_package_hash_profile_sha256: str, +) -> dict[str, Any]: + return { + "schema_version": "1.0", + "attestation_id": "acidslide-environment-attestation-v1", + "canonicalization": "RFC8785-JCS", + "attestation_state": "verified", + "attested_at": "2026-07-18T00:00:00Z", + "platform": "linux/amd64", + "oci_image_digest": oci_image_digest, + "build_inputs": { + "dockerfile_sha256": _digest("dockerfile"), + "grader_lockfile_sha256": _digest("grader-lockfile"), + "base_image_digest": _digest("base-image"), + "uv_image_digest": _digest("uv-image"), + }, + "runtime_versions": { + name: "1.0.0" + for name in ( + "libreoffice", + "poppler", + "python", + "pillow", + "numpy", + "scikit_image", + "lxml", + "grader", + "libfaketime", + "fontconfig", + ) + }, + "binary_inventory": [ + {"name": name, "path": f"/usr/bin/{name}", "sha256": _digest(name)} + for name in ("fontconfig", "libfaketime", "libreoffice", "pdftoppm", "python") + ], + "font_environment": { + "fontconfig_file": "/etc/fonts/fonts.conf", + "fontconfig_config_sha256": _digest("fontconfig"), + "font_manifest_sha256": font_manifest_sha256, + "discovered_fonts": [ + { + "path": "/usr/share/fonts/test.ttf", + "sha256": _digest("test-font"), + } + ], + "exact_manifest_match": True, + }, + "process_environment": { + "FAKETIME": "@2025-01-01 00:00:00", + "FAKETIME_DONT_FAKE_MONOTONIC": "1", + "FAKETIME_NO_CACHE": "1", + "LD_PRELOAD": "/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1", + "TZ": "UTC", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US.UTF-8", + }, + "export_contract": { + "libreoffice_command": [ + "libreoffice", + "--headless", + "-env:UserInstallation=file://", + "--convert-to", + "pdf", + "--outdir", + "/work", + "/input/submission.pptx", + ], + "pdftoppm_command": [ + "pdftoppm", + "-png", + "-scale-to-x", + "1920", + "-scale-to-y", + "1080", + "/work/submission.pdf", + "/work/acidslide-render", + ], + "presentation_size_emu": {"cx": 12192000, "cy": 6858000}, + "allowed_page_counts": [5, 12, 20], + "width_px": 1920, + "height_px": 1080, + "color_mode": "RGB", + "reference_datetime": "2025-01-01T00:00:00Z", + "pdf_page_geometry": { + "numeric_parser": "exact-decimal-string", + "media_box": ["0", "0", "960.009448818898", "540"], + "crop_box": "absent-or-exactly-equal-to-media-box", + "rotate": "absent-or-zero", + }, + }, + "profile_hashes": { + "export_profile_sha256": _digest("export-profile"), + "png_profile_sha256": _digest("png-profile"), + "ssim_profile_sha256": _digest("ssim-profile"), + "json_schema_bundle_sha256": _digest("json-schema"), + "xsd_bundle_sha256": schema_bundle_sha256, + "schema_root_map_sha256": schema_root_map_sha256, + "mce_profile_sha256": mce_profile_sha256, + "scene_graph_profile_sha256": _digest("scene-graph-profile"), + "canonical_package_hash_profile_sha256": (canonical_package_hash_profile_sha256), + }, + "grader_source_tree_sha256": grader_source_tree_sha256, + "canary": { + "canary_id": "release-canary-v1", + "input_sha256": _digest("canary-input"), + "score_semantic_report_sha256": _digest("canary-report"), + }, + "verification": { + "architecture_verified": True, + "binary_hashes_verified": True, + "font_inventory_verified": True, + "clock_fixture_verified": True, + "network_disabled_verified": True, + }, + } + + +def test_production_refuses_unsafe_defaults() -> None: + with pytest.raises(ValidationError) as error: + Settings(app_env="production") + message = str(error.value) + assert "PostgreSQL" in message + assert "GRADER_IMAGE_DIGEST" in message + assert "development key" in message + assert "ENVIRONMENT_ATTESTATION_JSON must hash" in message + assert "ACTIVE_GRADER_PACKAGE_SHA256" in message + + +def test_isolated_container_uids_match_the_canonical_images() -> None: + settings = Settings(_env_file=None) + assert settings.grader_uid == 10001 + assert settings.quarantine_uid == 10001 + + +def test_environment_attestation_must_be_a_json_object() -> None: + with pytest.raises(ValidationError, match="must contain a JSON object"): + Settings(environment_attestation_json="[]") + + +def test_schema_valid_frozen_production_configuration_is_accepted() -> None: + oci_image_digest = _digest("official-image") + grader_source_tree_sha256 = _digest("grader-source") + font_manifest_sha256 = _digest("font-manifest") + schema_bundle_sha256 = _digest("xsd-bundle") + schema_root_map_sha256 = _digest("schema-root-map") + mce_profile_sha256 = _digest("mce-profile") + canonical_profile_sha256 = _digest("canonical-package-profile") + attestation = _production_attestation( + oci_image_digest=oci_image_digest, + grader_source_tree_sha256=grader_source_tree_sha256, + font_manifest_sha256=font_manifest_sha256, + schema_bundle_sha256=schema_bundle_sha256, + schema_root_map_sha256=schema_root_map_sha256, + mce_profile_sha256=mce_profile_sha256, + canonical_package_hash_profile_sha256=canonical_profile_sha256, + ) + attestation_sha256 = f"sha256:{hashlib.sha256(rfc8785.dumps(attestation)).hexdigest()}" + quarantine_key = Ed25519PrivateKey.generate() + now = datetime.now(UTC) + verification_keys = json.dumps( + { + "production-key": { + "public_key": encode_public_key(quarantine_key.public_key()), + "not_before": utc_text(now - timedelta(days=1)), + "not_after": utc_text(now + timedelta(days=1)), + "revoked_at": None, + } + } + ) + + settings = Settings( + app_env="production", + database_url="postgresql+psycopg://service@db/acidslide", + public_base_url="https://acidslide.dev", + admin_api_key="a" * 40, + api_key_pepper="p" * 40, + encryption_key="qQ_1yAQvQABKVF1vpj6AEuM9UgGPy0L7GtJ2y6kODGc=", + grader_image_digest=oci_image_digest, + quarantine_image_digest=_digest("quarantine-image"), + active_scoring_manifest_sha256=_digest("scoring-manifest"), + active_grader_source_tree_sha256=grader_source_tree_sha256, + active_environment_attestation_sha256=attestation_sha256, + environment_attestation_json=json.dumps(attestation), + active_grader_package_sha256=_digest("grader-package"), + active_prompt_bundle_sha256=_digest("prompt-bundle"), + active_scored_assertion_inventory_sha256=_digest("assertion-inventory"), + active_checklist_bundle_sha256=_digest("checklist-bundle"), + active_quarantine_profile_sha256=_digest("quarantine-profile"), + active_mce_profile_sha256=mce_profile_sha256, + active_schema_bundle_sha256=schema_bundle_sha256, + active_schema_root_map_sha256=schema_root_map_sha256, + active_canonical_package_hash_profile_sha256=canonical_profile_sha256, + active_gold_byte_sha256=_digest("gold-original"), + active_gold_mce_resolved_package_sha256=_digest("gold-resolved"), + active_gold_canonical_package_sha256=_digest("gold-canonical"), + font_bundle_hash=font_manifest_sha256, + asset_manifest_hash=_digest("asset-manifest"), + quarantine_verification_keys_json=verification_keys, + ) + + assert settings.environment_attestation == attestation + assert settings.active_environment_attestation_sha256 == attestation_sha256 + + +def test_production_refuses_test_runner() -> None: + with pytest.raises(ValidationError) as error: + Settings( + app_env="production", + database_url="postgresql+psycopg://service@db/acidslide", + public_base_url="https://acidslide.dev", + admin_api_key="a" * 40, + api_key_pepper="p" * 40, + encryption_key="qQ_1yAQvQABKVF1vpj6AEuM9UgGPy0L7GtJ2y6kODGc=", + grader_image_digest="sha256:" + "a" * 64, + allow_insecure_test_runner=True, + ) + assert "ALLOW_INSECURE_TEST_RUNNER" in str(error.value) diff --git a/acidslide-v1/service/tests/test_quarantine.py b/acidslide-v1/service/tests/test_quarantine.py new file mode 100644 index 0000000..87cb484 --- /dev/null +++ b/acidslide-v1/service/tests/test_quarantine.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest + +from acidslide_service.config import Settings +from acidslide_service.quarantine import inspect_pptx + +from .conftest import make_pptx + + +@pytest.mark.parametrize( + ("kwargs", "reason"), + [ + ({"external_relationship": True}, "External OOXML"), + ({"nested_archive": True}, "Nested archive"), + ({"ole": True}, "Hidden OLE"), + ({"traversal": True}, "Unsafe path"), + ], +) +def test_evasion_techniques_are_rejected( + tmp_path: Path, + settings: Settings, + kwargs: dict[str, bool], + reason: str, +) -> None: + path = tmp_path / "attack.pptx" + path.write_bytes(make_pptx(**kwargs)) + result = inspect_pptx(path, 1, settings) + assert not result.passed + assert reason in result.reason + + +def test_extension_and_magic_are_both_checked(tmp_path: Path, settings: Settings) -> None: + renamed = tmp_path / "renamed.pptx" + renamed.write_bytes(b"not-a-zip") + assert "not an OOXML" in inspect_pptx(renamed, 1, settings).reason + + wrong_extension = tmp_path / "deck.zip" + wrong_extension.write_bytes(make_pptx()) + assert "extension" in inspect_pptx(wrong_extension, 1, settings).reason + + +def test_valid_tier_deck_passes(tmp_path: Path, settings: Settings) -> None: + path = tmp_path / "valid.pptx" + path.write_bytes(make_pptx(12)) + result = inspect_pptx(path, 2, settings) + assert result.passed + assert result.slide_count == 12 + + +def test_safe_embedded_chart_workbook_passes(tmp_path: Path, settings: Settings) -> None: + path = tmp_path / "chart-deck.pptx" + path.write_bytes(make_pptx(5, embedded_spreadsheet=True)) + result = inspect_pptx(path, 1, settings) + assert result.passed + assert result.slide_count == 5 diff --git a/acidslide-v1/service/tests/test_quarantine_handoff.py b/acidslide-v1/service/tests/test_quarantine_handoff.py new file mode 100644 index 0000000..286d5d1 --- /dev/null +++ b/acidslide-v1/service/tests/test_quarantine_handoff.py @@ -0,0 +1,772 @@ +from __future__ import annotations + +import asyncio +import io +import json +import os +import subprocess +import zipfile +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Any + +import pytest +from fastapi import UploadFile +from fastapi.testclient import TestClient +from lxml import etree +from sqlalchemy import select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service.config import Settings +from acidslide_service.models import QuarantineVerdictUse, Submission +from acidslide_service.quarantine_handoff import ( + ObjectBinding, + QuarantineHandoffError, + QuarantineJobBinding, + build_payload, + jcs_bytes, + load_private_key, + load_public_key, + load_verification_keys, + parse_utc, + require_binding, + sign_payload, + verify_envelope, +) +from acidslide_service.quarantine_runner import ( + DockerQuarantineRunner, + InsecureInProcessQuarantineRunner, + LocalSubprocessQuarantineRunner, + QuarantineRunnerError, + QuarantineRunResult, +) +from acidslide_service.quarantine_worker import claim_next_quarantine, quarantine_once +from acidslide_service.service import claim_next_submission, recover_stale_jobs +from acidslide_service.storage import InvalidUploadError, new_object_version, store_upload +from acidslide_service.worker import ( + consume_verdict, + lease_verdict, + verify_and_consume_handoff, + worker_once, +) + +from .conftest import create_campaign, create_org, make_pptx, metadata, submit +from .test_worker_and_leaderboard import FakeRunner + + +class FailingQuarantineRunner: + def assert_ready(self) -> None: + return None + + def inspect(self, **_kwargs: Any) -> QuarantineRunResult: + raise QuarantineRunnerError("orchestrator unavailable") + + +class RecordingDockerQuarantineRunner(DockerQuarantineRunner): + def __init__(self, settings: Settings, image_hash: str = "sha256:image") -> None: + super().__init__(settings) + self.image_hash = image_hash + self.commands: list[list[str]] = [] + + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + self.commands.append(args) + if args[:3] == ["docker", "image", "inspect"]: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": [f"acidslide/quarantine@{self.image_hash}"], + } + return subprocess.CompletedProcess(args, 0, json.dumps(identity), "") + output_mount = next( + value + for value in args + if value.startswith("type=bind,source=") and "target=/output" in value + ) + output = Path(output_mount.split(",", 2)[1].removeprefix("source=")) + (output / "resolved.pptx").write_bytes(b"resolved") + (output / "verdict.json").write_text('{"sandbox":"ok"}', encoding="utf-8") + return subprocess.CompletedProcess(args, 0, "", "") + + +class QuarantineIdentityRunner(DockerQuarantineRunner): + def __init__(self, settings: Settings, identity: object) -> None: + super().__init__(settings) + self.identity = identity + + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + return subprocess.CompletedProcess(args, 0, json.dumps(self.identity), "") + + +def _row(sessions: sessionmaker[Session], submission_id: str) -> Submission: + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + session.expunge(submission) + return submission + + +def _resign( + sessions: sessionmaker[Session], + settings: Settings, + submission_id: str, + mutate: Any, +) -> None: + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + assert submission.quarantine_envelope_json is not None + payload = dict(submission.quarantine_envelope_json["payload"]) + mutate(payload) + submission.quarantine_envelope_json = sign_payload( + payload, + load_private_key(settings.quarantine_signing_private_key), + ) + session.commit() + + +def test_api_control_plane_never_opens_zip_or_xml( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + deck = make_pptx() + + def forbidden(*_args: Any, **_kwargs: Any) -> Any: + raise AssertionError("API process attempted ZIP/XML parsing") + + monkeypatch.setattr(zipfile, "ZipFile", forbidden) + monkeypatch.setattr(etree, "fromstring", forbidden) + response = client.post( + "/v1/submissions", + headers={"Authorization": f"Bearer {api_key}"}, + files={ + "metadata": (None, json.dumps(metadata(campaign_id)), "application/json"), + "file": ( + "submission.pptx", + deck, + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + ), + }, + ) + assert response.status_code == 202 + assert response.json()["status"] == "quarantining" + + assert quarantine_once( + settings, + sessions, + LocalSubprocessQuarantineRunner(settings), + "subprocess-quarantine", + ) + assert _row(sessions, response.json()["submission_id"]).status == "queued" + + +def test_original_object_tamper_is_rejected_before_parse( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + campaign_id = create_campaign(client, api_key) + response = client.post( + "/v1/submissions", + headers={"X-API-Key": api_key}, + files={ + "metadata": (None, json.dumps(metadata(campaign_id)), "application/json"), + "file": ("submission.pptx", make_pptx(), "application/octet-stream"), + }, + ) + submission = _row(sessions, response.json()["submission_id"]) + original = Path(submission.file_path) + os.chmod(original, 0o600) + original.write_bytes(original.read_bytes() + b"tamper") + os.chmod(original, 0o400) + + assert quarantine_once( + settings, + sessions, + InsecureInProcessQuarantineRunner(settings), + "quarantine", + ) + rejected = _row(sessions, submission.id) + assert rejected.status == "rejected" + assert rejected.campaign_slot is None + assert "digest or size changed" in (rejected.error_message or "") + + +def test_quarantine_orchestrator_failure_and_attempt_exhaustion_release_slots( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + first_campaign = create_campaign(client, api_key) + first = client.post( + "/v1/submissions", + headers={"X-API-Key": api_key}, + files={ + "metadata": (None, json.dumps(metadata(first_campaign)), "application/json"), + "file": ("submission.pptx", make_pptx(), "application/octet-stream"), + }, + ) + assert quarantine_once(settings, sessions, FailingQuarantineRunner(), "quarantine") + failed = _row(sessions, first.json()["submission_id"]) + assert failed.status == "failed" + assert failed.error_code == "quarantine_unavailable" + assert failed.campaign_slot is None + + second_campaign = create_campaign(client, api_key) + second = client.post( + "/v1/submissions", + headers={"X-API-Key": api_key}, + files={ + "metadata": (None, json.dumps(metadata(second_campaign)), "application/json"), + "file": ("submission.pptx", make_pptx(), "application/octet-stream"), + }, + ) + with sessions() as session: + exhausted = session.scalar( + select(Submission).where(Submission.id == second.json()["submission_id"]) + ) + assert exhausted is not None + exhausted.quarantine_attempt = 3 + session.commit() + assert claim_next_quarantine(session, settings, "quarantine") is None + exhausted_row = _row(sessions, second.json()["submission_id"]) + assert exhausted_row.status == "failed" + assert exhausted_row.campaign_slot is None + + +def test_opaque_upload_rejects_extension_and_magic_only( + settings: Settings, +) -> None: + wrong_extension = UploadFile(filename="deck.zip", file=io.BytesIO(make_pptx())) + with pytest.raises(InvalidUploadError, match="extension"): + asyncio.run(store_upload(wrong_extension, "wrong-extension", settings)) + + wrong_magic = UploadFile(filename="deck.pptx", file=io.BytesIO(b"not-a-package")) + with pytest.raises(InvalidUploadError, match="not an OOXML"): + asyncio.run(store_upload(wrong_magic, "wrong-magic", settings)) + + +def test_resolved_tamper_fails_closed_before_grader( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + submission = _row(sessions, submission_id) + assert submission.resolved_file_path is not None, ( + submission.status, + submission.error_code, + submission.error_message, + ) + resolved = Path(submission.resolved_file_path) + os.chmod(resolved, 0o600) + resolved.write_bytes(resolved.read_bytes() + b"tamper") + os.chmod(resolved, 0o400) + + assert worker_once(settings, sessions, FakeRunner(), "worker") + failed = _row(sessions, submission_id) + assert failed.status == "failed" + assert failed.error_code == "quarantine_handoff_mismatch" + + +def test_signature_expiry_object_version_and_binding_tamper_fail_closed( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + + expired_id = submit(client, api_key).json()["submission_id"] + + def expire(payload: dict[str, Any]) -> None: + payload["issued_at"] = "2020-01-01T00:00:00Z" + payload["expires_at"] = "2020-01-01T00:01:00Z" + + _resign(sessions, settings, expired_id, expire) + assert worker_once(settings, sessions, FakeRunner(), "worker") + assert _row(sessions, expired_id).error_code == "quarantine_handoff_mismatch" + + version_id = submit(client, api_key).json()["submission_id"] + with sessions() as session: + versioned = session.scalar(select(Submission).where(Submission.id == version_id)) + assert versioned is not None + versioned.resolved_object_version = new_object_version() + session.commit() + assert worker_once(settings, sessions, FakeRunner(), "worker") + assert _row(sessions, version_id).error_code == "quarantine_handoff_mismatch" + + binding_id = submit(client, api_key).json()["submission_id"] + + def substitute_slot(payload: dict[str, Any]) -> None: + payload["campaign_slot"] = 3 if payload["campaign_slot"] != 3 else 2 + + _resign(sessions, settings, binding_id, substitute_slot) + assert worker_once(settings, sessions, FakeRunner(), "worker") + assert _row(sessions, binding_id).error_code == "quarantine_handoff_mismatch" + + +def test_verdict_replay_is_database_rejected( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + verify_and_consume_handoff(session, submission, settings, "worker-one") + with pytest.raises(QuarantineHandoffError, match="already been consumed"): + verify_and_consume_handoff(session, submission, settings, "worker-two") + + +def test_verdict_cas_rejects_active_lease_stale_generation_and_consumed_replay( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + now = datetime.now(UTC) + with sessions() as session: + verdict = session.scalar( + select(QuarantineVerdictUse).where(QuarantineVerdictUse.submission_id == submission_id) + ) + assert verdict is not None + generation = lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-one", + lease_seconds=10, + now=now, + ) + assert generation == 1 + with pytest.raises(QuarantineHandoffError, match="active lease"): + lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-two", + lease_seconds=10, + now=now + timedelta(seconds=1), + ) + with pytest.raises(QuarantineHandoffError, match="expired, stale"): + consume_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-one", + generation=0, + now=now + timedelta(seconds=1), + ) + consume_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-one", + generation=generation, + now=now + timedelta(seconds=1), + ) + with pytest.raises(QuarantineHandoffError, match="already been consumed"): + lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-two", + lease_seconds=10, + now=now + timedelta(seconds=2), + ) + + +def test_expired_verdict_lease_reclaims_with_incremented_generation( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + now = datetime.now(UTC) + with sessions() as session: + verdict = session.scalar( + select(QuarantineVerdictUse).where(QuarantineVerdictUse.submission_id == submission_id) + ) + assert verdict is not None + first_generation = lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-one", + lease_seconds=10, + now=now, + ) + second_generation = lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-two", + lease_seconds=10, + now=now + timedelta(seconds=11), + ) + assert first_generation == 1 + assert second_generation == 2 + with pytest.raises(QuarantineHandoffError, match="expired, stale"): + consume_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-one", + generation=first_generation, + now=now + timedelta(seconds=12), + ) + consume_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker-two", + generation=second_generation, + now=now + timedelta(seconds=12), + ) + + +def test_verdict_lease_rejects_unissued_and_invalid_lifecycle_states( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + with sessions() as session, pytest.raises(QuarantineHandoffError, match="not issued"): + lease_verdict( + session, + verdict_id="missing", + submission_id="missing", + worker_id="worker", + lease_seconds=10, + ) + + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + with sessions() as session: + verdict = session.scalar( + select(QuarantineVerdictUse).where(QuarantineVerdictUse.submission_id == submission_id) + ) + assert verdict is not None + verdict.state = "corrupt" + session.commit() + with pytest.raises(QuarantineHandoffError, match="invalid lifecycle state"): + lease_verdict( + session, + verdict_id=verdict.verdict_id, + submission_id=submission_id, + worker_id="worker", + lease_seconds=10, + ) + + +def test_retry_after_consumption_requires_fresh_quarantine_verdict( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + with sessions() as session: + submission = claim_next_submission(session, settings, "crashed-worker") + assert submission is not None + assert submission.id == submission_id + verify_and_consume_handoff(session, submission, settings, "crashed-worker") + submission.grading_started_at = datetime.now(UTC) - timedelta( + seconds=settings.stale_job_seconds + 1 + ) + session.commit() + assert recover_stale_jobs(session, settings) == 1 + session.refresh(submission) + assert submission.status == "quarantining" + assert submission.quarantine_envelope_json is None + assert submission.resolved_object_version is None + + assert quarantine_once( + settings, + sessions, + InsecureInProcessQuarantineRunner(settings), + "replacement-quarantine", + ) + with sessions() as session: + verdicts = list( + session.scalars( + select(QuarantineVerdictUse).where( + QuarantineVerdictUse.submission_id == submission_id + ) + ) + ) + assert sorted(verdict.state for verdict in verdicts) == ["consumed", "issued"] + submission = session.get(Submission, submission_id) + assert submission is not None + assert submission.status == "queued" + + +def test_unknown_revoked_key_signature_and_exact_binding_are_rejected(settings: Settings) -> None: + now = datetime.now(UTC).replace(microsecond=0) + private_key = load_private_key(settings.quarantine_signing_private_key) + binding = ObjectBinding(new_object_version(), f"sha256:{'a' * 64}", 12) + resolved = ObjectBinding(new_object_version(), f"sha256:{'b' * 64}", 13) + profiles = { + "canonical_package_hash_profile_sha256": ( + settings.active_canonical_package_hash_profile_sha256 + ), + "mce_profile_sha256": settings.active_mce_profile_sha256, + "quarantine_profile_sha256": settings.active_quarantine_profile_sha256, + "schema_bundle_sha256": settings.active_schema_bundle_sha256, + "schema_root_map_sha256": settings.active_schema_root_map_sha256, + } + payload = build_payload( + verdict_id="one-use", + key_id=settings.quarantine_signing_key_id, + outcome="accepted", + reason="", + original=binding, + resolved=resolved, + submission_id="submission", + campaign_id="campaign", + campaign_slot=1, + quarantine_profile_sha256=profiles["quarantine_profile_sha256"], + mce_profile_sha256=profiles["mce_profile_sha256"], + schema_bundle_sha256=profiles["schema_bundle_sha256"], + schema_root_map_sha256=profiles["schema_root_map_sha256"], + canonical_package_hash_profile_sha256=profiles["canonical_package_hash_profile_sha256"], + canonical_package_hash_v1=f"sha256:{'c' * 64}", + gold_duplicate_check={ + "byte_match": False, + "canonical_package_match": False, + "decision": "clear", + }, + schema_validation={"performed": True, "valid": True, "violations": []}, + run_kind="submission", + control_authorization_sha256=None, + control_authorization_object_version=None, + issued_at=now, + expires_at=now + timedelta(minutes=5), + ) + envelope = sign_payload(payload, private_key) + keys = load_verification_keys(settings.quarantine_verification_keys_json) + assert verify_envelope(envelope, keys, now=now) == payload + + tampered = dict(envelope) + tampered["signature"] = "A" + str(tampered["signature"])[1:] + with pytest.raises(QuarantineHandoffError, match="signature is invalid"): + verify_envelope(tampered, keys, now=now) + + unknown_payload = dict(payload) + unknown_payload["key_id"] = "unknown" + with pytest.raises(QuarantineHandoffError, match="key is unknown"): + verify_envelope(sign_payload(unknown_payload, private_key), keys, now=now) + + key_document = json.loads(settings.quarantine_verification_keys_json) + key_document[settings.quarantine_signing_key_id]["revoked_at"] = ( + (now - timedelta(seconds=1)).isoformat().replace("+00:00", "Z") + ) + revoked = load_verification_keys(json.dumps(key_document)) + with pytest.raises(QuarantineHandoffError, match="inactive or revoked"): + verify_envelope(envelope, revoked, now=now) + + with pytest.raises(QuarantineHandoffError, match="campaign_slot"): + require_binding( + payload, + original=binding, + resolved=resolved, + submission_id="submission", + campaign_id="campaign", + campaign_slot=2, + expected_profiles=profiles, + ) + + +def test_malformed_handoff_primitives_fail_closed(settings: Settings) -> None: + with pytest.raises(QuarantineHandoffError, match="Original object binding is missing"): + QuarantineJobBinding.from_dict({}) + with pytest.raises(QuarantineHandoffError, match="binding is malformed"): + QuarantineJobBinding.from_dict({"original": {}}) + with pytest.raises(QuarantineHandoffError, match="not JCS canonicalizable"): + jcs_bytes({"non_finite": float("nan")}) + with pytest.raises(QuarantineHandoffError, match="private key"): + load_private_key("not-base64") + with pytest.raises(QuarantineHandoffError, match="public key"): + load_public_key("not-base64") + with pytest.raises(QuarantineHandoffError, match="UTC timestamp"): + parse_utc("not-utc", "issued_at") + with pytest.raises(QuarantineHandoffError, match="is invalid"): + parse_utc("not-a-dateZ", "issued_at") + with pytest.raises(QuarantineHandoffError, match="JSON is invalid"): + load_verification_keys("{") + with pytest.raises(QuarantineHandoffError, match="No quarantine verification keys"): + load_verification_keys("{}") + with pytest.raises(QuarantineHandoffError, match="record is malformed"): + load_verification_keys('{"": {}}') + with pytest.raises(QuarantineHandoffError, match="Public key is missing"): + load_verification_keys('{"missing-public": {}}') + + now = datetime.now(UTC).replace(microsecond=0) + original = ObjectBinding(new_object_version(), f"sha256:{'a' * 64}", 12) + resolved = ObjectBinding(new_object_version(), f"sha256:{'b' * 64}", 13) + common = { + "verdict_id": "malformed-test", + "key_id": settings.quarantine_signing_key_id, + "outcome": "accepted", + "reason": "", + "original": original, + "resolved": resolved, + "submission_id": "submission", + "campaign_id": "campaign", + "campaign_slot": 1, + "quarantine_profile_sha256": settings.active_quarantine_profile_sha256, + "mce_profile_sha256": settings.active_mce_profile_sha256, + "schema_bundle_sha256": settings.active_schema_bundle_sha256, + "schema_root_map_sha256": settings.active_schema_root_map_sha256, + "canonical_package_hash_profile_sha256": ( + settings.active_canonical_package_hash_profile_sha256 + ), + "canonical_package_hash_v1": f"sha256:{'c' * 64}", + "gold_duplicate_check": {"decision": "clear"}, + "schema_validation": {"performed": True, "valid": True}, + "run_kind": "submission", + "control_authorization_sha256": None, + "control_authorization_object_version": None, + } + with pytest.raises(QuarantineHandoffError, match="expiry must follow"): + build_payload(**common, issued_at=now, expires_at=now) # type: ignore[arg-type] + + payload = build_payload( + **common, # type: ignore[arg-type] + issued_at=now, + expires_at=now + timedelta(minutes=5), + ) + private_key = load_private_key(settings.quarantine_signing_private_key) + keys = load_verification_keys(settings.quarantine_verification_keys_json) + with pytest.raises(QuarantineHandoffError, match="envelope is missing"): + verify_envelope(None, keys, now=now) + with pytest.raises(QuarantineHandoffError, match="algorithm is invalid"): + verify_envelope({"signature_algorithm": "RSA"}, keys, now=now) + with pytest.raises(QuarantineHandoffError, match="payload is missing"): + verify_envelope({"signature_algorithm": "Ed25519"}, keys, now=now) + unsupported = dict(payload) + unsupported["schema_version"] = "2.0" + with pytest.raises(QuarantineHandoffError, match="schema version is unsupported"): + verify_envelope(sign_payload(unsupported, private_key), keys, now=now) + backwards = dict(payload) + backwards["issued_at"] = (now + timedelta(minutes=2)).isoformat().replace("+00:00", "Z") + backwards["expires_at"] = (now + timedelta(minutes=1)).isoformat().replace("+00:00", "Z") + with pytest.raises(QuarantineHandoffError, match="expiry is invalid"): + verify_envelope(sign_payload(backwards, private_key), keys, now=now) + unsigned = sign_payload(payload, private_key) + unsigned.pop("signature") + with pytest.raises(QuarantineHandoffError, match="signature is missing"): + verify_envelope(unsigned, keys, now=now) + missing_id = dict(payload) + missing_id["verdict_id"] = "" + with pytest.raises(QuarantineHandoffError, match="verdict_id"): + require_binding( + missing_id, + original=original, + resolved=resolved, + submission_id="submission", + campaign_id="campaign", + campaign_slot=1, + expected_profiles=payload["profiles"], + ) + + +def test_production_docker_quarantine_command_is_constrained( + settings: Settings, + tmp_path: Path, +) -> None: + pinned = settings.model_copy( + update={ + "quarantine_image_digest": "sha256:image", + "storage_path": tmp_path / "data", + } + ) + original = tmp_path / "original.pptx" + original.write_bytes(make_pptx()) + runner = RecordingDockerQuarantineRunner(pinned) + runner.assert_ready() + result = runner.inspect( + original_path=original, + binding=QuarantineJobBinding( + submission_id="00000000-0000-0000-0000-000000000001", + campaign_id="00000000-0000-0000-0000-000000000002", + campaign_slot=1, + tier=1, + original=ObjectBinding(new_object_version(), f"sha256:{'a' * 64}", 1), + resolved_object_version=new_object_version(), + ), + ) + assert result.envelope == {"sandbox": "ok"} + command = next(args for args in runner.commands if args[:2] == ["docker", "run"]) + for required in ( + "--network", + "none", + "--platform", + "linux/amd64", + "--read-only", + "--cap-drop", + "ALL", + "--security-opt", + "no-new-privileges", + "--pids-limit", + "--memory", + "--cpus", + "--user", + ): + assert required in command + assert "target=/input/original.pptx,readonly" in " ".join(command) + for real_time_override in ( + "LD_PRELOAD=", + "FAKETIME=", + "FAKETIME_DONT_FAKE_MONOTONIC=", + "FAKETIME_NO_CACHE=", + ): + assert real_time_override in command + result.cleanup() + + mismatch = RecordingDockerQuarantineRunner(pinned, "sha256:other") + with pytest.raises(QuarantineRunnerError, match="RepoDigest does not match"): + mismatch.assert_ready() + + +def test_quarantine_runner_rejects_malformed_image_identity(settings: Settings) -> None: + with pytest.raises(QuarantineRunnerError, match="identity is malformed"): + QuarantineIdentityRunner(settings, {}).assert_ready() + + +def test_quarantine_runner_rejects_ambiguous_unpinned_repodigests( + settings: Settings, +) -> None: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": [ + f"one/quarantine@sha256:{'a' * 64}", + f"two/quarantine@sha256:{'b' * 64}", + ], + } + with pytest.raises(QuarantineRunnerError, match="ambiguous"): + QuarantineIdentityRunner(settings, identity).assert_ready() + + +def test_development_quarantine_runner_can_fall_back_to_config_digest( + settings: Settings, +) -> None: + identity = { + "id": f"sha256:{'a' * 64}", + "os": "linux", + "architecture": "amd64", + "repo_digests": None, + } + assert QuarantineIdentityRunner(settings, identity)._image_hash() == f"sha256:{'a' * 64}" diff --git a/acidslide-v1/service/tests/test_runner_and_webhooks.py b/acidslide-v1/service/tests/test_runner_and_webhooks.py new file mode 100644 index 0000000..124f77a --- /dev/null +++ b/acidslide-v1/service/tests/test_runner_and_webhooks.py @@ -0,0 +1,638 @@ +from __future__ import annotations + +import hashlib +import json +import subprocess +from pathlib import Path +from typing import Any + +import pytest +import rfc8785 +from fastapi.testclient import TestClient +from sqlalchemy import select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service import webhooks +from acidslide_service.config import Settings +from acidslide_service.models import Submission, WebhookDelivery +from acidslide_service.runner import ( + DockerGradingRunner, + GradingError, + ReferenceControlBinding, + RendererCrashError, + ScoringCohortBinding, +) +from acidslide_service.security import encrypt_secret +from acidslide_service.service import scoring_cohort_id +from acidslide_service.webhooks import ( + UnsafeWebhookURLError, + deliver_webhook, + validate_webhook_url, + webhook_signature, +) + +from .conftest import ( + ENVIRONMENT_HASH, + GRADER_SOURCE_HASH, + MANIFEST_HASH, + create_org, + hosted_artifact_binding, + submit, +) + + +class RecordingRunner(DockerGradingRunner): + def __init__(self, settings: Settings) -> None: + super().__init__(settings) + self.commands: list[list[str]] = [] + + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + self.commands.append(args) + if args[:3] == ["docker", "image", "inspect"]: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": ["acidslide/grader@sha256:image"], + } + return subprocess.CompletedProcess(args, 0, json.dumps(identity), "") + if "attest-environment" in args: + attestation = self.settings.environment_attestation + envelope = { + "environment_attestation": attestation, + "environment_attestation_sha256": ( + f"sha256:{hashlib.sha256(rfc8785.dumps(attestation)).hexdigest()}" + ), + } + return subprocess.CompletedProcess(args, 0, json.dumps(envelope), "") + if args[:2] == ["docker", "run"]: + report: dict[str, Any] = { + "benchmark_version": "acidslide-v1.0.0", + "grader_version": "test", + "fidelity_score": 0.5, + "passed_items": 1, + "total_items": 2, + "deck_passed": False, + "eligible": True, + "tier_scores": {}, + "anti_cheat_flags": [], + } + return subprocess.CompletedProcess(args, 0, json.dumps(report), "") + return subprocess.CompletedProcess(args, 0, "", "") + + +class ImageIdentityRunner(DockerGradingRunner): + def __init__(self, settings: Settings, identity: object) -> None: + super().__init__(settings) + self.identity = identity + + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + return subprocess.CompletedProcess(args, 0, json.dumps(self.identity), "") + + +class CanaryRecordingRunner(RecordingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + if args[:2] == ["docker", "run"] and any( + "ACIDSLIDE_CANARY_RESULT=" in argument for argument in args + ): + payload = { + "report": { + "run_kind": "reference_control", + "score_semantic_report_sha256": f"sha256:{'a' * 64}", + }, + "canonical_png_sha256s": [f"sha256:{page:064x}" for page in range(1, 21)], + "scene_graph_sha256": f"sha256:{'b' * 64}", + } + self.commands.append(args) + return subprocess.CompletedProcess( + args, + 0, + "renderer log\nACIDSLIDE_CANARY_RESULT=" + + json.dumps(payload, separators=(",", ":")), + "", + ) + return super()._run(args, timeout) + + +def test_grading_container_has_required_isolation( + tmp_path: Path, + settings: Settings, + monkeypatch: pytest.MonkeyPatch, +) -> None: + path = tmp_path / "deck.pptx" + path.write_bytes(b"deck") + cleanup: list[list[str]] = [] + + def record_cleanup(args: list[str], **_kwargs: Any) -> subprocess.CompletedProcess[str]: + cleanup.append(args) + return subprocess.CompletedProcess(args, 0, "", "") + + monkeypatch.setattr(subprocess, "run", record_cleanup) + runner = RecordingRunner(settings) + outcome = runner.grade( + path, + 1, + "00000000-0000-0000-0000-000000000001", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding(), + ) + command = next( + args + for args in runner.commands + if args[:2] == ["docker", "run"] + and "--read-only" in args + and "attest-environment" not in args + ) + attestation_command = next(args for args in runner.commands if "attest-environment" in args) + for required in ( + "--network", + "none", + "--read-only", + "--cap-drop", + "ALL", + "--security-opt", + "no-new-privileges", + "--pids-limit", + "--memory", + "--cpus", + "--user", + ): + assert required in command + assert "readonly" in " ".join(command) + assert "--network" in attestation_command + assert "none" in attestation_command + assert "--read-only" in attestation_command + assert "/input/submission.pptx" not in attestation_command + assert "from acidslide.pipeline import run_resolved_pipeline" in command[-6] + assert "from acidslide.pipeline import run_pipeline" not in command[-6] + context = json.loads(command[-2]) + assert context["grading_mode"] == "hosted" + assert context["submission_id"] == "00000000-0000-0000-0000-000000000001" + assert context["oci_image_digest"] == "sha256:image" + assert json.loads(command[-1]) == {"performed": True, "valid": True, "violations": []} + assert outcome.provenance["environment_hash"].startswith("sha256:") + assert any( + args[-2:] == [f"{settings.grader_uid}:{settings.grader_uid}", "/input/submission.pptx"] + for args in runner.commands + ) + assert any(args[:4] == ["docker", "volume", "rm", "-f"] for args in cleanup) + + +def test_reference_control_runner_emits_exact_canary_surfaces( + tmp_path: Path, + settings: Settings, +) -> None: + path = tmp_path / "gold-resolved.pptx" + path.write_bytes(b"resolved-gold") + runner = CanaryRecordingRunner(settings) + outcome = runner.grade_reference_control( + path, + 2, + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + ReferenceControlBinding( + control_authorization_sha256=f"sha256:{'1' * 64}", + original_submission_sha256=f"sha256:{'2' * 64}", + mce_resolved_package_sha256=f"sha256:{'3' * 64}", + canonical_package_hash_profile_sha256=f"sha256:{'4' * 64}", + canonical_package_hash_v1=f"sha256:{'5' * 64}", + schema_bundle_sha256=f"sha256:{'6' * 64}", + schema_root_map_sha256=f"sha256:{'7' * 64}", + mce_profile_sha256=f"sha256:{'8' * 64}", + ), + ) + assert outcome.report["run_kind"] == "reference_control" + assert len(outcome.canonical_png_sha256s) == 20 + assert outcome.scene_graph_sha256 == f"sha256:{'b' * 64}" + command = next( + args + for args in runner.commands + if any("ACIDSLIDE_CANARY_RESULT=" in argument for argument in args) + ) + assert command[command.index("--network") : command.index("--network") + 2] == [ + "--network", + "none", + ] + assert "--read-only" in command + assert "readonly" in " ".join(command) + context = json.loads(command[-1]) + assert context["run_kind"] == "reference_control" + assert context["targeted_tier"] == 2 + assert context["submission_id"] is None + assert context["gold_duplicate_check"] == "byte_match" + + +def test_grading_runner_surfaces_sanitized_container_failure( + tmp_path: Path, + settings: Settings, + monkeypatch: pytest.MonkeyPatch, +) -> None: + class FailingGradeRunner(RecordingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + if ( + args[:2] == ["docker", "run"] + and "--read-only" in args + and "attest-environment" not in args + ): + raise subprocess.CalledProcessError( + 1, + args, + stderr="canonical grader canary failure", + ) + return super()._run(args, timeout) + + monkeypatch.setattr( + subprocess, + "run", + lambda args, **_kwargs: subprocess.CompletedProcess(args, 0, "", ""), + ) + path = tmp_path / "deck.pptx" + path.write_bytes(b"deck") + + with pytest.raises(RendererCrashError, match="canonical grader canary failure"): + FailingGradeRunner(settings).grade( + path, + 1, + "00000000-0000-0000-0000-000000000001", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding(), + ) + + +def test_grading_runner_rejects_runtime_attestation_tamper( + tmp_path: Path, + settings: Settings, +) -> None: + class TamperedAttestationRunner(RecordingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + if "attest-environment" in args: + envelope = { + "environment_attestation": {"tampered": True}, + "environment_attestation_sha256": ENVIRONMENT_HASH, + } + return subprocess.CompletedProcess(args, 0, json.dumps(envelope), "") + return super()._run(args, timeout) + + path = tmp_path / "deck.pptx" + path.write_bytes(b"deck") + runner = TamperedAttestationRunner(settings) + with pytest.raises(GradingError, match="envelope hash is invalid"): + runner.grade( + path, + 1, + "00000000-0000-0000-0000-000000000001", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding(), + ) + + +@pytest.mark.parametrize( + ("stdout", "message"), + [ + ("no envelope", "emitted no JSON"), + ("{invalid", "emitted invalid JSON"), + ("{}", "envelope is malformed"), + ], +) +def test_runtime_attestation_rejects_malformed_container_output( + stdout: str, + message: str, + settings: Settings, +) -> None: + class EnvelopeRunner(DockerGradingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + return subprocess.CompletedProcess(args, 0, stdout, "") + + with pytest.raises(GradingError, match=message): + EnvelopeRunner(settings)._attest_environment("sha256:image", ENVIRONMENT_HASH) + + +def test_runtime_attestation_binds_active_release_and_cohort(settings: Settings) -> None: + class EnvelopeRunner(DockerGradingRunner): + def __init__(self, runtime_settings: Settings, payload: dict[str, Any]) -> None: + super().__init__(runtime_settings) + self.payload = payload + + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + digest = f"sha256:{hashlib.sha256(rfc8785.dumps(self.payload)).hexdigest()}" + return subprocess.CompletedProcess( + args, + 0, + json.dumps( + { + "environment_attestation": self.payload, + "environment_attestation_sha256": digest, + } + ), + "", + ) + + with pytest.raises(GradingError, match="active release"): + EnvelopeRunner(settings, {"runtime": "different"})._attest_environment( + "sha256:image", ENVIRONMENT_HASH + ) + + active_mismatch = settings.model_copy( + update={"active_environment_attestation_sha256": f"sha256:{'f' * 64}"} + ) + with pytest.raises(GradingError, match="service state"): + EnvelopeRunner(active_mismatch, {})._attest_environment("sha256:image", ENVIRONMENT_HASH) + + with pytest.raises(GradingError, match="scoring cohort"): + EnvelopeRunner(settings, {})._attest_environment("sha256:image", f"sha256:{'f' * 64}") + + +def test_runtime_attestation_surfaces_container_failure(settings: Settings) -> None: + class FailedAttestationRunner(DockerGradingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + raise subprocess.CalledProcessError(2, args, stderr="binary hash mismatch") + + with pytest.raises(GradingError, match="binary hash mismatch"): + FailedAttestationRunner(settings)._attest_environment("sha256:image", ENVIRONMENT_HASH) + + +def test_grading_runner_rejects_image_attestation_mismatch( + tmp_path: Path, + settings: Settings, +) -> None: + path = tmp_path / "deck.pptx" + path.write_bytes(b"deck") + runner = RecordingRunner( + settings.model_copy( + update={ + "environment_attestation_json": json.dumps( + {"oci_image_digest": f"sha256:{'f' * 64}"} + ) + } + ) + ) + with pytest.raises(GradingError, match="environment attestation"): + runner.grade( + path, + 1, + "00000000-0000-0000-0000-000000000001", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding(), + ) + + +def test_grading_runner_rejects_non_frozen_platform( + tmp_path: Path, + settings: Settings, +) -> None: + class ArmRunner(RecordingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + if args[:3] == ["docker", "image", "inspect"]: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "arm64", + "repo_digests": ["acidslide/grader@sha256:image"], + } + return subprocess.CompletedProcess(args, 0, json.dumps(identity), "") + return super()._run(args, timeout) + + path = tmp_path / "deck.pptx" + path.write_bytes(b"deck") + with pytest.raises(GradingError, match="linux/amd64"): + ArmRunner(settings).grade( + path, + 1, + "00000000-0000-0000-0000-000000000001", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding(), + ) + + +@pytest.mark.parametrize( + "identity", + [ + None, + {}, + { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": ["not-a-digest"], + }, + ], +) +def test_grading_runner_rejects_malformed_image_identity( + identity: object, + settings: Settings, +) -> None: + with pytest.raises(RendererCrashError, match="identity is malformed"): + ImageIdentityRunner(settings, identity)._image_hash() + + +def test_grading_runner_rejects_unavailable_and_invalid_image_inspection( + settings: Settings, +) -> None: + class UnavailableRunner(DockerGradingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + raise OSError("docker unavailable") + + class InvalidJSONRunner(DockerGradingRunner): + def _run(self, args: list[str], timeout: int = 60) -> subprocess.CompletedProcess[str]: + return subprocess.CompletedProcess(args, 0, "{", "") + + with pytest.raises(RendererCrashError, match="image is unavailable"): + UnavailableRunner(settings)._image_hash() + with pytest.raises(RendererCrashError, match="identity is malformed"): + InvalidJSONRunner(settings)._image_hash() + + +def test_grading_runner_binds_attested_platform_and_single_manifest_digest( + settings: Settings, +) -> None: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": [f"acidslide/grader@sha256:{'a' * 64}"], + } + wrong_attestation = settings.model_copy( + update={"environment_attestation_json": json.dumps({"platform": "linux/arm64"})} + ) + with pytest.raises(GradingError, match="platform does not match"): + ImageIdentityRunner(wrong_attestation, identity)._image_hash() + unpinned = settings.model_copy(update={"grader_image_digest": ""}) + assert ImageIdentityRunner(unpinned, identity)._image_hash() == f"sha256:{'a' * 64}" + + +def test_grading_runner_collects_only_bounded_diff_artifacts( + tmp_path: Path, + settings: Settings, +) -> None: + runner = DockerGradingRunner(settings) + valid_dir = tmp_path / "valid" + valid_dir.mkdir() + (valid_dir / "diff-slide-02.png").write_bytes(b"two") + (valid_dir / "diff-slide-01.png").write_bytes(b"one") + artifacts = runner._collect_artifacts(valid_dir) + assert [artifact.name for artifact in artifacts] == [ + "diff-slide-01.png", + "diff-slide-02.png", + ] + + unsafe_dir = tmp_path / "unsafe" + unsafe_dir.mkdir() + (unsafe_dir / "directory").mkdir() + with pytest.raises(GradingError, match="unsafe filesystem entry"): + runner._collect_artifacts(unsafe_dir) + + unexpected_dir = tmp_path / "unexpected" + unexpected_dir.mkdir() + (unexpected_dir / "report.json").write_text("{}", encoding="utf-8") + with pytest.raises(GradingError, match="unexpected name"): + runner._collect_artifacts(unexpected_dir) + + large_dir = tmp_path / "large" + large_dir.mkdir() + with (large_dir / "diff-slide-01.png").open("wb") as stream: + stream.truncate(50 * 1024 * 1024 + 1) + with pytest.raises(GradingError, match="exceeds 50 MB"): + runner._collect_artifacts(large_dir) + + +def test_grading_runner_requires_configured_manifest_repodigest(settings: Settings) -> None: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": [f"acidslide/grader@sha256:{'a' * 64}"], + } + pinned = settings.model_copy(update={"grader_image_digest": f"sha256:{'b' * 64}"}) + with pytest.raises(GradingError, match="RepoDigest"): + ImageIdentityRunner(pinned, identity)._image_hash() + + +def test_grading_runner_rejects_ambiguous_unpinned_repodigests(settings: Settings) -> None: + identity = { + "id": "sha256:config", + "os": "linux", + "architecture": "amd64", + "repo_digests": [ + f"one/grader@sha256:{'a' * 64}", + f"two/grader@sha256:{'b' * 64}", + ], + } + with pytest.raises(GradingError, match="ambiguous"): + ImageIdentityRunner(settings, identity)._image_hash() + + +def test_development_grading_runner_can_fall_back_to_config_digest(settings: Settings) -> None: + identity = { + "id": f"sha256:{'a' * 64}", + "os": "linux", + "architecture": "amd64", + "repo_digests": None, + } + assert ImageIdentityRunner(settings, identity)._image_hash() == f"sha256:{'a' * 64}" + + +def test_webhook_signature_is_raw_body_hmac() -> None: + assert webhook_signature(b'{"status":"completed"}', "secret") == ( + "f221b3e5be7a7967fb814487442ac97c879375c1cd8fec3fec9c4476bed3589a" + ) + + +@pytest.mark.parametrize( + "url", + [ + "http://example.com/callback", + "https://127.0.0.1/callback", + "https://[::1]/callback", + "https://user:password@example.com/callback", + ], +) +def test_webhook_rejects_unsafe_destinations(url: str) -> None: + with pytest.raises(UnsafeWebhookURLError): + validate_webhook_url(url) + + +def test_delivery_signs_exact_body_and_records_attempt( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + captured: dict[str, Any] = {} + + def fake_post(url: str, body: bytes, headers: dict[str, str]) -> int: + captured.update(url=url, body=body, headers=headers) + return 204 + + monkeypatch.setattr(webhooks, "_post_pinned", fake_post) + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + submission.webhook_url = "https://hooks.example.com/acidslide" + submission.webhook_secret_encrypted = encrypt_secret("a-secret-at-least-16", settings) + session.commit() + payload = {"submission_id": submission.id, "status": "completed"} + assert deliver_webhook(session, submission, payload, settings) + delivery = session.scalar( + select(WebhookDelivery).where(WebhookDelivery.submission_id == submission.id) + ) + assert delivery is not None + assert delivery.attempt == 1 + assert delivery.response_status == 204 + assert captured["headers"]["X-AcidSlide-Signature"] == webhook_signature( + captured["body"], "a-secret-at-least-16" + ) diff --git a/acidslide-v1/service/tests/test_service_operations.py b/acidslide-v1/service/tests/test_service_operations.py new file mode 100644 index 0000000..f7d627c --- /dev/null +++ b/acidslide-v1/service/tests/test_service_operations.py @@ -0,0 +1,469 @@ +from __future__ import annotations + +import asyncio +import hashlib +import io +import json +import signal +import socket +import sys +import time +import uuid +from collections.abc import Callable +from datetime import UTC, datetime, timedelta +from pathlib import Path + +import pytest +from fastapi import UploadFile +from fastapi.testclient import TestClient +from sqlalchemy import select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service import cli, webhooks, worker +from acidslide_service.config import Settings +from acidslide_service.models import ( + Campaign, + GenerationProfile, + ModelIdentity, + ModelRevision, + Organization, + Submission, + SubmissionStatus, + WebhookDelivery, +) +from acidslide_service.runner import ( + GradeOutcome, + GradingError, + HostedArtifactBinding, + InsecureTestRunner, + ScoringCohortBinding, +) +from acidslide_service.security import encrypt_secret +from acidslide_service.service import ( + check_submission_limits, + claim_next_submission, + fail_submission, + recover_stale_jobs, + scoring_cohort_id, + status_payload, +) +from acidslide_service.storage import UploadTooLargeError, new_object_version, store_upload +from acidslide_service.webhooks import ( + UnsafeWebhookURLError, + deliver_webhook, + validate_webhook_url, +) +from acidslide_service.worker import Runner, worker_once + +from .conftest import ( + ENVIRONMENT_HASH, + GRADER_SOURCE_HASH, + MANIFEST_HASH, + create_org, + hosted_artifact_binding, + submit, +) + + +def add_organization(session: Session, name: str, quota: int = 30) -> Organization: + organization = Organization( + name=name, + key_prefix=f"prefix-{name}", + api_key_hash="hash", + monthly_quota=quota, + ) + session.add(organization) + session.flush() + return organization + + +def add_submission( + session: Session, + organization: Organization, + *, + status: str = SubmissionStatus.QUEUED.value, + attempt: int = 0, + created_at: datetime | None = None, + model_version: str = "v1", +) -> Submission: + model = ModelIdentity( + organization_id=organization.id, + display_name="model", + owner_attribution="submitter-attested", + ) + session.add(model) + session.flush() + revision = ModelRevision( + model_id=model.id, + display_name=model_version, + revision_note="test", + ) + session.add(revision) + session.flush() + timestamp = created_at or datetime.now(UTC) + profile_sha256 = f"sha256:{hashlib.sha256(revision.id.encode()).hexdigest()}" + session.add( + GenerationProfile( + generation_profile_sha256=profile_sha256, + organization_id=organization.id, + model_revision_id=revision.id, + canonical_profile_json={"permissions": {"human_intervention_permitted": False}}, + ) + ) + session.flush() + campaign = Campaign( + organization_id=organization.id, + model_id=model.id, + model_revision_id=revision.id, + tier=1, + benchmark_version="acidslide-v1.0.0", + prompt_variant="canonical", + scoring_cohort_id=scoring_cohort_id(MANIFEST_HASH, GRADER_SOURCE_HASH, ENVIRONMENT_HASH), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + assistance_class="unassisted", + generation_profile_sha256=profile_sha256, + window_id=str(uuid.uuid4()), + opens_at=timestamp - timedelta(minutes=1), + closes_at=timestamp + timedelta(days=7), + ) + session.add(campaign) + session.flush() + row = Submission( + organization_id=organization.id, + model_id=model.id, + model_revision_id=revision.id, + campaign_id=campaign.id, + campaign_slot=1, + tier=1, + benchmark_version="acidslide-v1.0.0", + prompt_variant="canonical", + status=status, + file_name="deck.pptx", + file_path="/private/deck.pptx", + file_sha256="0" * 64, + file_size_bytes=100, + original_object_version=new_object_version(), + efficiency_metrics={"generation_strategy": "direct"}, + attestation={"human_intervention": False}, + attempt=attempt, + created_at=timestamp, + queued_at=timestamp, + ) + session.add(row) + session.flush() + return row + + +def test_hourly_and_monthly_limits(settings: Settings, sessions: sessionmaker[Session]) -> None: + now = datetime.now(UTC) + with sessions() as session: + organization = add_organization(session, "limited", quota=1) + add_submission(session, organization, created_at=now - timedelta(minutes=2)) + session.commit() + hourly_settings = settings.model_copy(update={"submissions_per_hour": 1}) + hourly = check_submission_limits( + session, + organization, + campaign=add_submission( + session, organization, model_version="hourly-campaign" + ).campaign, + settings=hourly_settings, + now=now, + ) + assert hourly is not None + assert hourly.message == "Hourly submission limit reached" + + monthly_settings = settings.model_copy( + update={"submissions_per_hour": 100, "submissions_per_tuple_window": 100} + ) + monthly = check_submission_limits( + session, + organization, + campaign=add_submission( + session, organization, model_version="monthly-campaign" + ).campaign, + settings=monthly_settings, + now=now, + ) + assert monthly is not None + assert monthly.message == "Monthly organization quota reached" + + +def test_claim_fairness_skips_tenant_at_concurrency_cap( + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + now = datetime.now(UTC) + with sessions() as session: + busy = add_organization(session, "busy") + available = add_organization(session, "available") + for index in range(5): + add_submission( + session, + busy, + status=SubmissionStatus.GRADING.value, + model_version=f"active-{index}", + ) + add_submission(session, busy, created_at=now - timedelta(minutes=2), model_version="queued") + expected = add_submission( + session, + available, + created_at=now - timedelta(minutes=1), + model_version="available", + ) + session.commit() + claimed = claim_next_submission(session, settings, "worker-1") + assert claimed is not None + assert claimed.id == expected.id + assert claimed.status == SubmissionStatus.GRADING.value + + +def test_stale_recovery_and_failure_payload( + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + stale = datetime.now(UTC) - timedelta(hours=1) + with sessions() as session: + organization = add_organization(session, "recovery") + retry = add_submission( + session, + organization, + status=SubmissionStatus.GRADING.value, + attempt=1, + model_version="retry", + ) + retry.grading_started_at = stale + exhausted = add_submission( + session, + organization, + status=SubmissionStatus.GRADING.value, + attempt=3, + model_version="exhausted", + ) + exhausted.grading_started_at = stale + session.commit() + assert recover_stale_jobs(session, settings) == 2 + assert retry.status == SubmissionStatus.QUEUED.value + assert exhausted.status == SubmissionStatus.FAILED.value + assert status_payload(exhausted)["error"]["code"] == "grading_timeout" + + retry.status = SubmissionStatus.GRADING.value + fail_submission( + session, + retry, + code="renderer_crash", + message="Renderer stopped", + retryable=True, + ) + assert status_payload(retry)["error"] == { + "code": "renderer_crash", + "message": "Renderer stopped", + "retryable": True, + } + + +class ExpectedGradingErrorRunner: + def grade( + self, + _path: Path, + _tier: int, + _submission_id: str, + _cohort: ScoringCohortBinding, + _artifact: HostedArtifactBinding, + ) -> GradeOutcome: + raise GradingError("bad report") + + +class UnexpectedErrorRunner: + def grade( + self, + _path: Path, + _tier: int, + _submission_id: str, + _cohort: ScoringCohortBinding, + _artifact: HostedArtifactBinding, + ) -> GradeOutcome: + raise TypeError("unexpected") + + +@pytest.mark.parametrize( + ("runner", "error_code"), + [ + (ExpectedGradingErrorRunner(), "grading_failed"), + (UnexpectedErrorRunner(), "grading_failed"), + ], +) +def test_worker_failure_paths_do_not_publish( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + runner: Runner, + error_code: str, +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + assert worker_once(settings, sessions, runner, "worker") + response = client.get( + f"/v1/submissions/{submission_id}", + headers={"X-API-Key": api_key}, + ).json() + assert response["status"] == "failed" + assert response["error"]["code"] == error_code + + +def test_admin_cli_init_and_create_org( + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, + capsys: pytest.CaptureFixture[str], +) -> None: + initialized: list[bool] = [] + monkeypatch.setattr(cli, "initialize_database", lambda: initialized.append(True)) + monkeypatch.setattr(sys, "argv", ["acidslide-admin", "init-db"]) + cli.main() + assert initialized == [True] + assert "initialized" in capsys.readouterr().out + + monkeypatch.setattr(cli, "SessionLocal", sessions) + monkeypatch.setattr(cli, "get_settings", lambda: settings) + monkeypatch.setattr( + sys, + "argv", + ["acidslide-admin", "create-org", "CLI Lab", "--monthly-quota", "42"], + ) + cli.main() + payload = json.loads(capsys.readouterr().out) + assert payload["api_key"].startswith("asv1_") + with sessions() as session: + organization = session.scalar(select(Organization).where(Organization.name == "CLI Lab")) + assert organization is not None + assert organization.monthly_quota == 42 + + +def test_worker_run_initializes_and_exits_cleanly( + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + runtime_settings = settings.model_copy(update={"allow_insecure_test_runner": True}) + callbacks: dict[int, Callable[[int, object], None]] = {} + initialized: list[bool] = [] + monkeypatch.setattr(worker, "get_settings", lambda: runtime_settings) + monkeypatch.setattr(worker, "initialize_database", lambda: initialized.append(True)) + monkeypatch.setattr(worker, "start_http_server", lambda _port: None) + monkeypatch.setattr(worker, "SessionLocal", sessions) + + def capture_signal(signum: int, callback: Callable[[int, object], None]) -> None: + callbacks[signum] = callback + + monkeypatch.setattr(signal, "signal", capture_signal) + + def stop_on_first_poll(*_args: object) -> bool: + callback = callbacks[signal.SIGTERM] + callback(signal.SIGTERM, None) + return False + + monkeypatch.setattr(worker, "worker_once", stop_on_first_poll) + monkeypatch.setattr(time, "sleep", lambda _seconds: None) + worker.run() + assert initialized == [True] + + +def test_insecure_runner_requires_opt_in_and_returns_deterministic_grade( + settings: Settings, + tmp_path: Path, +) -> None: + with pytest.raises(RuntimeError, match="disabled"): + InsecureTestRunner(settings) + + submission = tmp_path / "submission.pptx" + submission.write_bytes(b"small-deck") + runner = InsecureTestRunner(settings.model_copy(update={"allow_insecure_test_runner": True})) + outcome = runner.grade( + submission, + 2, + "submission-id", + ScoringCohortBinding( + scoring_cohort_id=scoring_cohort_id( + MANIFEST_HASH, + GRADER_SOURCE_HASH, + ENVIRONMENT_HASH, + ), + scoring_manifest_sha256=MANIFEST_HASH, + grader_source_tree_sha256=GRADER_SOURCE_HASH, + environment_attestation_sha256=ENVIRONMENT_HASH, + ), + hosted_artifact_binding("submission-id"), + ) + + assert outcome.report["fidelity_score"] == 0.8 + assert outcome.report["tier_scores"] == {"level_2": {"fidelity_score": 0.8}} + assert outcome.report["verified_metrics"] == {"submission_file_size_bytes": 10} + assert outcome.provenance["environment_hash"] == "test-only" + + +def test_webhook_validation_accepts_public_dns_and_query( + monkeypatch: pytest.MonkeyPatch, +) -> None: + def resolve_public(*_args: object, **_kwargs: object) -> list[tuple[object, ...]]: + return [ + (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("8.8.8.8", 8443)), + (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("1.1.1.1", 8443)), + ] + + monkeypatch.setattr(socket, "getaddrinfo", resolve_public) + validate_webhook_url("https://hooks.example.com:8443/callback?event=grade") + + +def test_webhook_retries_transport_error_then_stops_on_unsafe_dns( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + _, api_key = create_org(client, "Webhook retry lab") + submission_id = submit(client, api_key).json()["submission_id"] + failures = iter([OSError("connection reset"), UnsafeWebhookURLError("DNS rebound")]) + pauses: list[float] = [] + + def fail_delivery(_url: str, _body: bytes, _headers: dict[str, str]) -> int: + raise next(failures) + + monkeypatch.setattr(webhooks, "_post_pinned", fail_delivery) + monkeypatch.setattr(time, "sleep", pauses.append) + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + assert deliver_webhook(session, submission, {}, settings) + submission.webhook_url = "https://hooks.example.com/acidslide" + submission.webhook_secret_encrypted = encrypt_secret("a-secret-at-least-16", settings) + session.commit() + + assert not deliver_webhook(session, submission, {"status": "failed"}, settings) + deliveries = list( + session.scalars( + select(WebhookDelivery) + .where(WebhookDelivery.submission_id == submission_id) + .order_by(WebhookDelivery.attempt) + ) + ) + + assert [(row.attempt, row.outcome) for row in deliveries] == [ + (1, "OSError"), + (2, "UnsafeWebhookURLError"), + ] + assert pauses == [1] + + +def test_oversize_upload_is_removed_and_closed(settings: Settings) -> None: + upload = UploadFile(filename="oversize.pptx", file=io.BytesIO(b"too-large")) + limited = settings.model_copy(update={"max_upload_bytes": 4, "upload_chunk_bytes": 3}) + + with pytest.raises(UploadTooLargeError, match="4-byte upload limit"): + asyncio.run(store_upload(upload, "oversize-submission", limited)) + + assert upload.file.closed + assert not (limited.storage_path / "staging" / "oversize-submission.upload").exists() + assert not (limited.storage_path / "submissions" / "oversize-submission.pptx").exists() diff --git a/acidslide-v1/service/tests/test_worker_and_leaderboard.py b/acidslide-v1/service/tests/test_worker_and_leaderboard.py new file mode 100644 index 0000000..86fd39e --- /dev/null +++ b/acidslide-v1/service/tests/test_worker_and_leaderboard.py @@ -0,0 +1,532 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest +from fastapi.testclient import TestClient +from sqlalchemy import select +from sqlalchemy.orm import Session, sessionmaker + +from acidslide_service import worker +from acidslide_service.config import Settings +from acidslide_service.models import Submission +from acidslide_service.runner import ( + ArtifactFile, + GradeOutcome, + HostedArtifactBinding, + ScoringCohortBinding, +) +from acidslide_service.worker import worker_once + +from .conftest import ( + ENVIRONMENT_HASH, + GRADER_SOURCE_HASH, + MANIFEST_HASH, + create_campaign, + create_model_revision, + create_org, + metadata, + register_generation_profile, + submit, +) + + +class FakeRunner: + def __init__(self, score: float = 0.875, *, eligible: bool = True) -> None: + self.score = score + self.eligible = eligible + self.seen_paths: list[Path] = [] + + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: + self.seen_paths.append(submission_path) + return GradeOutcome( + report={ + "benchmark_version": "acidslide-v1.0.0", + "grader_version": "grader-test-sha", + "environment_hash": "overridden-by-service", + "scoring_cohort_id": cohort.scoring_cohort_id, + "scoring_manifest_sha256": cohort.scoring_manifest_sha256, + "grader_source_tree_sha256": cohort.grader_source_tree_sha256, + "environment_attestation_sha256": cohort.environment_attestation_sha256, + "environment_attestation": {}, + "grader_package_sha256": f"sha256:{'a' * 64}", + "oci_image_digest": "sha256:image", + "prompt_bundle_sha256": f"sha256:{'b' * 64}", + "scored_assertion_inventory_sha256": f"sha256:{'c' * 64}", + "checklist_bundle_sha256": f"sha256:{'d' * 64}", + "schema_bundle_sha256": artifact.schema_bundle_sha256, + "schema_root_map_sha256": artifact.schema_root_map_sha256, + "mce_profile_sha256": artifact.mce_profile_sha256, + "asset_manifest_sha256": "sha256:assets", + "font_manifest_sha256": "sha256:fonts", + "grading_mode": "hosted", + "run_kind": "submission", + "canonical_package_hash_profile_sha256": ( + artifact.canonical_package_hash_profile_sha256 + ), + "canonical_package_hash_v1": artifact.canonical_package_hash_v1, + "gold_duplicate_check": artifact.gold_duplicate_check, + "generation_seed": artifact.generation_seed, + "submission_id": artifact.submission_id, + "campaign_id": artifact.campaign_id, + "robustness_group_id": artifact.robustness_group_id, + "campaign_slot": artifact.campaign_slot, + "submitter_id": artifact.submitter_id, + "model_key": artifact.model_key, + "model_revision_key": artifact.model_revision_key, + "targeted_tier": tier, + "prompt_variant": artifact.prompt_variant, + "assistance_class": artifact.assistance_class, + "generation_profile_sha256": artifact.generation_profile_sha256, + "submission_sha256": artifact.submission_sha256, + "mce_resolved_package_sha256": artifact.mce_resolved_package_sha256, + "gold_submission_sha256": f"sha256:{'8' * 64}", + "gold_mce_resolved_package_sha256": f"sha256:{'e' * 64}", + "gold_canonical_package_hash_v1": f"sha256:{'9' * 64}", + "attested_metrics": artifact.attested_metrics, + "attestation": artifact.attestation, + "submission": submission_path.name, + "schema_validation_performed": artifact.schema_validation_performed, + "schema_valid": artifact.schema_valid, + "verification_complete": True, + "scoring_completed": True, + "repair_triggered": False, + "grading_duration_seconds": 1.25, + "fidelity_score": self.score, + "campaign_contribution": self.score if self.eligible else 0.0, + "passed_items": 70, + "total_items": 80, + "deck_passed": False, + "eligible": self.eligible, + "tier_scores": {f"level_{tier}": {"fidelity_score": self.score}}, + "verified_metrics": { + "submission_file_size_bytes": submission_path.stat().st_size, + "grading_duration_seconds": 1.25, + "schema_valid": True, + }, + "anti_cheat_flags": [], + "slides": [], + "deck_items": [], + }, + provenance={ + "docker_image_hash": "sha256:image", + "oci_image_digest": "sha256:image", + "libreoffice_version": "24.2.7.2", + "font_bundle_hash": "sha256:fonts", + "font_manifest_sha256": "sha256:fonts", + "asset_manifest_hash": "sha256:assets", + "asset_manifest_sha256": "sha256:assets", + "environment_hash": ENVIRONMENT_HASH, + "environment_attestation_sha256": ENVIRONMENT_HASH, + "scoring_manifest_sha256": MANIFEST_HASH, + "grader_source_tree_sha256": GRADER_SOURCE_HASH, + "grader_package_sha256": f"sha256:{'a' * 64}", + "prompt_bundle_sha256": f"sha256:{'b' * 64}", + "scored_assertion_inventory_sha256": f"sha256:{'c' * 64}", + "checklist_bundle_sha256": f"sha256:{'d' * 64}", + "schema_bundle_sha256": artifact.schema_bundle_sha256, + "schema_root_map_sha256": artifact.schema_root_map_sha256, + "mce_profile_sha256": artifact.mce_profile_sha256, + "gold_submission_sha256": f"sha256:{'8' * 64}", + "gold_mce_resolved_package_sha256": f"sha256:{'e' * 64}", + "gold_canonical_package_hash_v1": f"sha256:{'9' * 64}", + }, + ) + + +class ArtifactRunner(FakeRunner): + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: + outcome = super().grade(submission_path, tier, submission_id, cohort, artifact) + artifact_dir = submission_path.parents[4] / "artifacts" / submission_id + artifact_dir.mkdir(parents=True) + artifact_path = artifact_dir / "diff-slide-01.png" + artifact_path.write_bytes(b"\x89PNG\r\n\x1a\nprivate-diff") + return GradeOutcome( + outcome.report, + outcome.provenance, + ( + ArtifactFile( + name=artifact_path.name, + path=artifact_path, + size_bytes=artifact_path.stat().st_size, + sha256="7c7c2c71743e6442f8a1679af79950ed1ef94d9d7eff5aa7feaed28cf3f319d1", + ), + ), + ) + + +class SchemaDiagnosticRunner(FakeRunner): + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: + assert artifact.schema_validation_performed is True + assert artifact.schema_valid is False + assert artifact.schema_violations == ("schema-invalid-test",) + outcome = super().grade(submission_path, tier, submission_id, cohort, artifact) + report = { + **outcome.report, + "schema_valid": False, + "schema_validation_performed": True, + "visual_verification_performed": False, + "verification_complete": False, + "scoring_completed": False, + "fidelity_score": None, + "campaign_contribution": 0.0, + "passed_items": 0, + "total_items": 0, + "deck_passed": False, + "eligible": False, + "tier_scores": {"level_1": None, "level_2": None, "level_3": None}, + "disqualification_state": "completed_ineligible", + "ineligibility_reasons": ["schema_validation_failed"], + "schema_violations": [{"code": "schema_invalid_test"}], + } + return GradeOutcome(report, outcome.provenance) + + +class TamperedReportRunner(FakeRunner): + def __init__(self, tamper: str) -> None: + super().__init__() + self.tamper = tamper + + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: + outcome = super().grade(submission_path, tier, submission_id, cohort, artifact) + if self.tamper == "binding": + outcome.report["campaign_id"] = "00000000-0000-0000-0000-000000000000" + elif self.tamper == "missing_release": + outcome.report.pop("grader_package_sha256") + elif self.tamper == "release_mismatch": + outcome.report["grader_package_sha256"] = f"sha256:{'f' * 64}" + else: + outcome.report["environment_attestation"] = {"tampered": True} + return outcome + + +def test_worker_grades_only_the_resolved_package( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + original_path = Path(submission.file_path) + assert submission.resolved_file_path is not None + resolved_path = Path(submission.resolved_file_path) + + runner = FakeRunner() + assert worker_once(settings, sessions, runner, "resolved-only-worker") + assert runner.seen_paths == [resolved_path] + assert original_path not in runner.seen_paths + + +def test_production_worker_does_not_claim_work_without_a_current_canary( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client, "Canary blocked worker") + submission_id = submit(client, api_key).json()["submission_id"] + runner = FakeRunner() + production = settings.model_copy(update={"app_env": "production"}) + + assert worker_once(production, sessions, runner, "canary-blocked-worker") is False + assert runner.seen_paths == [] + with sessions() as session: + submission = session.get(Submission, submission_id) + assert submission is not None + assert submission.status == "queued" + assert submission.worker_id is None + + +def test_schema_invalid_diagnostic_report_occupies_zeroed_slot( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + _, api_key = create_org(client, "Schema diagnostic lab") + submission_id = submit(client, api_key).json()["submission_id"] + verify_handoff = worker.verify_and_consume_handoff + + def diagnostic_handoff( + session: Session, + submission: Submission, + runtime_settings: Settings, + worker_id: str, + ) -> tuple[Path, dict[str, object]]: + resolved_path, handoff = verify_handoff(session, submission, runtime_settings, worker_id) + submission.schema_validation_json = { + "performed": True, + "valid": False, + "violations": ["schema-invalid-test"], + } + return resolved_path, handoff + + monkeypatch.setattr(worker, "verify_and_consume_handoff", diagnostic_handoff) + assert worker_once(settings, sessions, SchemaDiagnosticRunner(), "diagnostic-worker") + + status = client.get(f"/v1/submissions/{submission_id}", headers={"X-API-Key": api_key}) + assert status.status_code == 200 + payload = status.json() + assert payload["status"] == "completed" + assert payload["campaign_slot"] == 1 + assert payload["result"]["fidelity_score"] is None + assert payload["result"]["campaign_score"] == 0.0 + assert payload["result"]["eligible"] is False + + ledger = client.get("/v1/leaderboard/runs").json() + row = next(run for run in ledger["runs"] if run["submission_id"] == submission_id) + assert row["fidelity_score"] is None + assert row["campaign_score"] == 0.0 + assert row["eligible"] is False + + +def test_unperformed_schema_result_fails_before_report_and_releases_slot( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], + monkeypatch: pytest.MonkeyPatch, +) -> None: + _, api_key = create_org(client, "Unperformed schema lab") + submission_id = submit(client, api_key).json()["submission_id"] + verify_handoff = worker.verify_and_consume_handoff + + def unperformed_handoff( + session: Session, + submission: Submission, + runtime_settings: Settings, + worker_id: str, + ) -> tuple[Path, dict[str, object]]: + resolved_path, handoff = verify_handoff(session, submission, runtime_settings, worker_id) + submission.schema_validation_json = { + "performed": False, + "valid": False, + "violations": [], + } + return resolved_path, handoff + + class RunnerMustNotStart(FakeRunner): + def grade( + self, + submission_path: Path, + tier: int, + submission_id: str, + cohort: ScoringCohortBinding, + artifact: HostedArtifactBinding, + ) -> GradeOutcome: + raise AssertionError("grader must not start for an unperformed schema result") + + monkeypatch.setattr(worker, "verify_and_consume_handoff", unperformed_handoff) + assert worker_once(settings, sessions, RunnerMustNotStart(), "unperformed-worker") + + status = client.get(f"/v1/submissions/{submission_id}", headers={"X-API-Key": api_key}).json() + assert status["status"] == "failed" + assert status["campaign_slot"] is None + assert status["error"]["code"] == "quarantine_handoff_mismatch" + + +@pytest.mark.parametrize( + "tamper", + ["binding", "missing_release", "release_mismatch", "environment_attestation"], +) +def test_worker_rejects_report_context_tampering( + tamper: str, + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client, f"Tampered report {tamper}") + submission_id = submit(client, api_key).json()["submission_id"] + assert worker_once(settings, sessions, TamperedReportRunner(tamper), "tamper-worker") + + status = client.get(f"/v1/submissions/{submission_id}", headers={"X-API-Key": api_key}).json() + assert status["status"] == "failed" + assert status["campaign_slot"] is None + assert status["error"]["code"] == "grading_failed" + + +def test_worker_completes_private_report_then_publishes( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + accepted = submit(client, api_key) + submission_id = accepted.json()["submission_id"] + assert worker_once(settings, sessions, FakeRunner(), "test-worker") + + status = client.get( + f"/v1/submissions/{submission_id}", headers={"Authorization": f"Bearer {api_key}"} + ) + assert status.status_code == 200 + assert status.json()["status"] == "completed" + assert status.json()["result"]["environment_hash"] == ENVIRONMENT_HASH + assert status.json()["result"]["verification_scope"] == "artifact_conformance" + assert ( + status.json()["result"]["verification_label"] + == "grading-verified artifact score; generation-attested" + ) + assert client.get(f"/v1/submissions/{submission_id}/report").status_code == 404 + private = client.get( + f"/v1/submissions/{submission_id}/report", + headers={"X-API-Key": api_key}, + ) + assert private.status_code == 200 + assert private.json()["environment_hash"] == ENVIRONMENT_HASH + + leaderboard = client.get("/v1/leaderboard?view=detail").json() + assert leaderboard["entries"][0]["provisional"] is True + assert leaderboard["entries"][0]["aggregate_score"] is None + assert leaderboard["entries"][0]["environment_attestation_sha256"] == ENVIRONMENT_HASH + assert leaderboard["entries"][0]["runs"][0]["submission_id"] == submission_id + run_ledger = client.get("/v1/leaderboard/runs").json() + public_run = run_ledger["runs"][0] + assert public_run["campaign_slot"] == 1 + assert public_run["campaign_score"] == 0.875 + assert public_run["grading_mode"] == "hosted" + assert public_run["run_kind"] == "submission" + assert public_run["submission_sha256"].startswith("sha256:") + assert public_run["gold_duplicate_check"] == "clear" + assert public_run["grader_package_sha256"] == f"sha256:{'a' * 64}" + assert public_run["environment_attestation"] == {} + assert public_run["report_sha256"].startswith("sha256:") + assert client.get("/v1/leaderboard/history").json()["snapshots"] + + published = client.post( + f"/v1/submissions/{submission_id}/publish-report", + headers={"X-API-Key": api_key}, + ) + assert published.status_code == 200 + assert client.get(f"/v1/submissions/{submission_id}/report").status_code == 200 + assert client.get(f"/v1/submissions/{submission_id}/report?format=html").status_code == 200 + + +def test_robustness_requires_all_variants_and_human_assisted_is_separate( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + _, revision_key = create_model_revision(client, api_key) + cohort = client.get("/v1/versions").json()["active_scoring_cohort_id"] + profile_sha256 = register_generation_profile(client, api_key, revision_key) + group = client.post( + "/v1/robustness-groups", + headers={"X-API-Key": api_key}, + json={ + "model_revision_key": revision_key, + "scoring_cohort_id": cohort, + "tier": 1, + "assistance_class": "unassisted", + "generation_profile_sha256": profile_sha256, + }, + ) + assert group.status_code == 201, group.text + campaigns = group.json()["campaigns"] + scores = {"canonical": 0.9, "paraphrase-a": 0.82, "paraphrase-b": 0.86} + for variant, score in scores.items(): + for _ in range(3): + assert ( + submit( + client, + api_key, + submission_metadata=metadata(campaigns[variant]), + ).status_code + == 202 + ) + assert worker_once(settings, sessions, FakeRunner(score), "worker") + payload = client.get("/v1/leaderboard").json() + assert len(payload["entries"]) == 3 + assert { + entry["tier_scores"]["level_1"]["robustness_score"] for entry in payload["entries"] + } == {0.82} + completed_group = client.get( + f"/v1/robustness-groups/{group.json()['robustness_group_id']}", + headers={"X-API-Key": api_key}, + ).json() + assert completed_group["status"] == "completed" + assert completed_group["robustness_score"] == 0.82 + + assisted_campaign = create_campaign(client, api_key, assistance_class="human-assisted") + for _ in range(3): + assisted = metadata(assisted_campaign) + assisted["attestation"]["human_intervention"] = True + assert submit(client, api_key, submission_metadata=assisted).status_code == 202 + assert worker_once(settings, sessions, FakeRunner(0.99), "worker") + separated = client.get("/v1/leaderboard").json() + assert len(separated["entries"]) == 3 + assert separated["human_assisted_entries"][0]["aggregate_score"] == 0.99 + + +def test_run_record_is_single_write( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, api_key = create_org(client) + submission_id = submit(client, api_key).json()["submission_id"] + assert worker_once(settings, sessions, FakeRunner(), "worker") + with sessions() as session: + submission = session.scalar(select(Submission).where(Submission.id == submission_id)) + assert submission is not None + assert submission.run is not None + assert len(submission.run.report_sha256) == 64 + assert submission.run.grading_started_at <= submission.run.grading_completed_at + submission.run.report_sha256 = "0" * 64 + with pytest.raises(RuntimeError, match="immutable"): + session.commit() + session.rollback() + + +def test_diff_artifacts_are_private_and_tenant_scoped( + client: TestClient, + settings: Settings, + sessions: sessionmaker[Session], +) -> None: + _, owner_key = create_org(client, "Artifact owner") + _, stranger_key = create_org(client, "Stranger") + submission_id = submit(client, owner_key).json()["submission_id"] + assert worker_once(settings, sessions, ArtifactRunner(), "worker") + + endpoint = f"/v1/submissions/{submission_id}/artifacts" + assert client.get(endpoint).status_code == 401 + assert client.get(endpoint, headers={"X-API-Key": stranger_key}).json()["artifacts"] == [] + listing = client.get(endpoint, headers={"X-API-Key": owner_key}) + assert listing.status_code == 200 + assert listing.json()["retention_days"] == 90 + artifact = listing.json()["artifacts"][0] + assert artifact["name"] == "diff-slide-01.png" + download = client.get(artifact["url"], headers={"X-API-Key": owner_key}) + assert download.status_code == 200 + assert download.headers["cache-control"] == "private, no-store" + assert download.content.startswith(b"\x89PNG") + assert client.get(artifact["url"], headers={"X-API-Key": stranger_key}).status_code == 404 diff --git a/acidslide-v1/service/uv.lock b/acidslide-v1/service/uv.lock new file mode 100644 index 0000000..8e04d71 --- /dev/null +++ b/acidslide-v1/service/uv.lock @@ -0,0 +1,1972 @@ +version = 1 +revision = 3 +requires-python = ">=3.12, <3.15" + +[[package]] +name = "acidslide-service" +version = "1.0.0a1" +source = { editable = "." } +dependencies = [ + { name = "alembic" }, + { name = "cryptography" }, + { name = "fastapi" }, + { name = "jinja2" }, + { name = "jsonschema" }, + { name = "prometheus-client" }, + { name = "psycopg", extra = ["binary"] }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "rfc8785" }, + { name = "sqlalchemy" }, + { name = "uvicorn", extra = ["standard"] }, +] + +[package.optional-dependencies] +dev = [ + { name = "httpx" }, + { name = "lxml" }, + { name = "lxml-stubs" }, + { name = "mypy" }, + { name = "pip-audit" }, + { name = "playwright" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "ruff" }, + { name = "types-jsonschema" }, + { name = "types-pyyaml" }, +] + +[package.metadata] +requires-dist = [ + { name = "alembic", specifier = ">=1.16,<2" }, + { name = "cryptography", specifier = ">=48.0.1,<49" }, + { name = "fastapi", specifier = ">=0.116,<1" }, + { name = "httpx", marker = "extra == 'dev'", specifier = ">=0.28,<1" }, + { name = "jinja2", specifier = ">=3.1.6,<4" }, + { name = "jsonschema", specifier = ">=4.25,<5" }, + { name = "lxml", marker = "extra == 'dev'", specifier = ">=6.1,<7" }, + { name = "lxml-stubs", marker = "extra == 'dev'", specifier = ">=0.5.1,<1" }, + { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.17,<2" }, + { name = "pip-audit", marker = "extra == 'dev'", specifier = ">=2.10,<3" }, + { name = "playwright", marker = "extra == 'dev'", specifier = ">=1.55,<2" }, + { name = "prometheus-client", specifier = ">=0.22,<1" }, + { name = "psycopg", extras = ["binary"], specifier = ">=3.2.9,<4" }, + { name = "pydantic-settings", specifier = ">=2.10,<3" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3,<10" }, + { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=6.2,<7" }, + { name = "python-multipart", specifier = ">=0.0.20,<1" }, + { name = "rfc8785", specifier = ">=0.1.4,<1" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12,<1" }, + { name = "sqlalchemy", specifier = ">=2.0.41,<3" }, + { name = "types-jsonschema", marker = "extra == 'dev'", specifier = ">=4.25,<5" }, + { name = "types-pyyaml", marker = "extra == 'dev'", specifier = ">=6.0.12,<7" }, + { name = "uvicorn", extras = ["standard"], specifier = ">=0.35,<1" }, +] +provides-extras = ["dev"] + +[[package]] +name = "alembic" +version = "1.18.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mako" }, + { name = "sqlalchemy" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/cc/ac0bed8e562e7407fe55c3ba85a4dce86e6dbd8730887bd1e406a6c5c18a/alembic-1.18.5.tar.gz", hash = "sha256:1554982221dd17e9a749b53902407578eb305e453f71999e8c7f0a48389fff8e", size = 2060480, upload-time = "2026-06-25T15:20:54.888Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/78/5fe6dc3a3a5b2f5a2a4faef8bfe336d5fa049a38884ab3172e0098160c01/alembic-1.18.5-py3-none-any.whl", hash = "sha256:06d8ba9d04558022f5395e9317de03d270f3dced49cee01f89fe7a13c26f14bc", size = 264664, upload-time = "2026-06-25T15:20:56.673Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "boolean-py" +version = "5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/cf/85379f13b76f3a69bca86b60237978af17d6aa0bc5998978c3b8cf05abb2/boolean_py-5.0.tar.gz", hash = "sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95", size = 37047, upload-time = "2025-04-03T10:39:49.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/ca/78d423b324b8d77900030fa59c4aa9054261ef0925631cd2501dd015b7b7/boolean_py-5.0-py3-none-any.whl", hash = "sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9", size = 26577, upload-time = "2025-04-03T10:39:48.449Z" }, +] + +[[package]] +name = "cachecontrol" +version = "0.14.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/f6/c972b32d80760fb79d6b9eeb0b3010a46b89c0b23cf6329417ff7886cd22/cachecontrol-0.14.4.tar.gz", hash = "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1", size = 16150, upload-time = "2025-11-14T04:32:13.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/79/c45f2d53efe6ada1110cf6f9fca095e4ff47a0454444aefdde6ac4789179/cachecontrol-0.14.4-py3-none-any.whl", hash = "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b", size = 22247, upload-time = "2025-11-14T04:32:11.733Z" }, +] + +[package.optional-dependencies] +filecache = [ + { name = "filelock" }, +] + +[[package]] +name = "certifi" +version = "2026.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, + { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" }, + { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" }, + { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" }, + { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" }, + { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" }, + { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" }, + { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" }, + { url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" }, + { url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" }, + { url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" }, + { url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" }, + { url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/42/6dbc00b8cd16011691203e33570fa42ed5746599a2e878112d16eab403a3/charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", size = 151185, upload-time = "2026-07-07T14:33:30.781Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/f920afd1a23c58ccd53c1d36085a71893a4737ff5e66e0371efab6809850/charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", size = 162557, upload-time = "2026-07-07T14:33:32.176Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/0386d43a261ff4e4b30c5857af7df877254b46bec7b9d1b74b6bf969a90b/charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", size = 152665, upload-time = "2026-07-07T14:33:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "7.15.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/d0/55fe630f4cf94e3fcba868240fad8c8cdd1f764e2a932f8926347e6ec4cd/coverage-7.15.2.tar.gz", hash = "sha256:3df60dc267f0a2ca23cb7a9ab1109c62b9335ffbf519fcfe167157c28c09b81d", size = 927741, upload-time = "2026-07-15T18:56:19.558Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/50/eb5bf42e531611a9f8d272556b1ed4de503f84a91413584094487cf69f8f/coverage-7.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1adac78e5abc7c5438f7a209c9ca69d06542f0bf481d728b6989ea80b813fdf9", size = 221587, upload-time = "2026-07-15T18:54:18.439Z" }, + { url = "https://files.pythonhosted.org/packages/06/d1/da99af464c335d4e023a6efcd7ec30f63b88a43c93745154ab74ffb31cea/coverage-7.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b868acc62aa5de3be7a9d05c2333bf8359ca987e43f9cb30ff8fbda6a024ab73", size = 221943, upload-time = "2026-07-15T18:54:20.062Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8a/13c42723d61ca447eafa18732e8141dd6a63f2732e1c7e1502c182dd88d7/coverage-7.15.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6f6966fc30e6f06ca8f98fb0ce51eda6b111b3ee8d066a8b1ec9e77fa06ab55d", size = 253450, upload-time = "2026-07-15T18:54:21.765Z" }, + { url = "https://files.pythonhosted.org/packages/d7/29/99021303f98fbdcb63504b4d07bea4cc025b9b2dd907c4f07c85d50a0dab/coverage-7.15.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:68af907f595ab01a78f794932ff3bdf929c316d3000810d38dbc247129e26f8b", size = 256187, upload-time = "2026-07-15T18:54:23.4Z" }, + { url = "https://files.pythonhosted.org/packages/f9/a8/fd503715ed6ca9c5d742923aa5209257340b367a867b2ced0c7d4ba8a0b9/coverage-7.15.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afa29e2eff3d5729267e2cb2fd4ce9d61c952932fb2694e34ccb5d9540c6a296", size = 257301, upload-time = "2026-07-15T18:54:25.183Z" }, + { url = "https://files.pythonhosted.org/packages/da/40/3f4b8fb409810036ebc2857d36adc0498c6e957b5df0290c5036b2e143f1/coverage-7.15.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bbf44513ceb1589e31948e20eafbde9deaface90e1a1afa5f5f77b4423d17ce6", size = 259562, upload-time = "2026-07-15T18:54:27.204Z" }, + { url = "https://files.pythonhosted.org/packages/0b/8a/9bdffbef47db77cce3d6b02a28f7e919b19f0106c4b080c2c2246040f885/coverage-7.15.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9deddf09eecb717b7f980414b43d90a5b22ff3967d2949ab29cb0aa83d9e9098", size = 253841, upload-time = "2026-07-15T18:54:29.134Z" }, + { url = "https://files.pythonhosted.org/packages/1b/1e/9031efde019d31a06646261fce6dfc5c3c74e951e27a71e5c9a424563178/coverage-7.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae901f7e55ba405c84ee1cab3d3e962e4e871e4a2bcb9c90911adbd69b42ac5a", size = 255221, upload-time = "2026-07-15T18:54:31.142Z" }, + { url = "https://files.pythonhosted.org/packages/56/db/787acde872389fc84a9ef9d8cd1ccc658e391ab4cb5b28092a714426a394/coverage-7.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a0f47002c6eeb7c280228467a4cb0cc15ca2103a8421b986b2d3ec04a0f9bd8b", size = 253366, upload-time = "2026-07-15T18:54:32.886Z" }, + { url = "https://files.pythonhosted.org/packages/2f/9b/6f57bc4b93c842eef1695f8cdaf2318e35e7ba54f5ba80d84be213ab7858/coverage-7.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd7a5beb7af3e864a13b1f0fb26efd3695da43ef0daf71e586adfffaf34d5b2", size = 257434, upload-time = "2026-07-15T18:54:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/88/26/b3186a21b2acc83e451118978905c81c7072c3333707804db09a78c096a2/coverage-7.15.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:97a5c5457a9fb1d6c4e06cfb5dc835871fbfb6a6a51addc9e925bdeff5ef7440", size = 252935, upload-time = "2026-07-15T18:54:36.548Z" }, + { url = "https://files.pythonhosted.org/packages/20/c2/c9f3376b2e717ea69ed7a6e9a5fcab968fb0b290db6cf4bd9a1fc7541b75/coverage-7.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0901cfe6c13bcd2302da4f83e884555d2a22bda6e4c476f09ef204ba20ca536e", size = 254807, upload-time = "2026-07-15T18:54:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e1/dfc15401f4a8aaeb486e1ba3e9e3c40522a6e38bd0ecf0b3f29cb8082957/coverage-7.15.2-cp312-cp312-win32.whl", hash = "sha256:b171bdd71cb7ff792bf32e376173b0ace7e7963e7e57c58dfc42063a6a7174cd", size = 223641, upload-time = "2026-07-15T18:54:40.103Z" }, + { url = "https://files.pythonhosted.org/packages/91/40/81b6d809d320cd366ec5bdf8176575e897dcb8efe7fb4b489ef9e93e4d13/coverage-7.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:582edc45c2040543fef83341be23c43024a3ab3ae0c2d8bc498a06282905ad40", size = 224172, upload-time = "2026-07-15T18:54:41.882Z" }, + { url = "https://files.pythonhosted.org/packages/ef/28/9f14ec438149f7de557f45518f09b4a7917b795cc37083aa7db482693f8c/coverage-7.15.2-cp312-cp312-win_arm64.whl", hash = "sha256:a638db90c61cd219aeee65e83a24fdaa57269a741ae0cf773309208ac862cee3", size = 223556, upload-time = "2026-07-15T18:54:43.674Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d5/f8c838e6b7282976f7c918884b792df7a0c42c5bba5d99c60ad2d221d56d/coverage-7.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1121caa19159a38b5463eaae4b1e1fde81e525b15ecc5e000cd5b1a108f743a8", size = 221606, upload-time = "2026-07-15T18:54:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/bf/37/97c926376364f66298cc44893b89cdf17b8bc406376497c4061ae4b8a8ff/coverage-7.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a300c6934e0989c327b9e8a1e110329da4641149f872bbe9f70168be66da76c1", size = 221982, upload-time = "2026-07-15T18:54:47.341Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/a36050a6e83c2135ee0776f452ca3948224befc6d7f26acecc082d0c106a/coverage-7.15.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2617f8799d268fabdeef42a7e89ac3a23e1deee9025427db2df970f99a89a578", size = 252972, upload-time = "2026-07-15T18:54:49.2Z" }, + { url = "https://files.pythonhosted.org/packages/31/d3/06b5f1daf95f0f15ab05bd75f26ba5f3c8b33d0bb72f3aaa3cf41d1bad3a/coverage-7.15.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7dc2950a2992cd676d35c20ae63522836deeb034f08874699d14068710af3dc1", size = 255569, upload-time = "2026-07-15T18:54:51.098Z" }, + { url = "https://files.pythonhosted.org/packages/81/1c/9afb3f8de2b8d36960391c48559a2e3ff96594b58099f115921549ea8d0d/coverage-7.15.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e36686f7a442185db2400b3df171aac520869faf9deb59df687d28659eda2a6", size = 256806, upload-time = "2026-07-15T18:54:53.145Z" }, + { url = "https://files.pythonhosted.org/packages/64/d8/b989f96061a5e32d82fddd1b1b9ff48a7c8f8ae7606f0e80fd9de54b1e33/coverage-7.15.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d29ca7bd67af6e12e74632d65f026eabc1364da5c254494cd914446a28a3ef7", size = 258936, upload-time = "2026-07-15T18:54:55.015Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fa/f99771f5110457c7b511c1935ca49ddf288218eaa84322e028b9334146ae/coverage-7.15.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:db9c8438057e5b0f6a22a0af99c0c1d26b57fbbdbd1be5861ddb8f897fcc3a2d", size = 253178, upload-time = "2026-07-15T18:54:57.527Z" }, + { url = "https://files.pythonhosted.org/packages/f6/96/c098a6044d119c751ceede7be91035fa8310170ec24a6523aff72f0a5793/coverage-7.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:63022c4c8dec1d0342f05c3ede99842fe3d007689acc45e86f123a1746e4a026", size = 254934, upload-time = "2026-07-15T18:54:59.41Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a2/1457b3a7a50c8d77500103b97a046db863e2f59a1cf6d2f814595f349885/coverage-7.15.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6c0be82b4d4aa5b2704e08518e2252f3e3d110164bcca826816801052e48a7aa", size = 252898, upload-time = "2026-07-15T18:55:01.338Z" }, + { url = "https://files.pythonhosted.org/packages/6c/0e/76958874c471ecfcdde0d2b2747bb2c61bdbf34a40636f4ce9db9923e643/coverage-7.15.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4510fb9cdf6bb02dfa6af0be4a534b8102d086e22e4a33f8836df663da3d660d", size = 257056, upload-time = "2026-07-15T18:55:03.243Z" }, + { url = "https://files.pythonhosted.org/packages/7c/7c/3d7c4e3bf58baa40327dc7edc2272b17cf02299366d52763db1b0ca1556a/coverage-7.15.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:42ec3d989421b174a2ab607c1539f24127ad362757b7f1c0c0d7a2993f7eb37b", size = 252718, upload-time = "2026-07-15T18:55:05.029Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b8/1cecffed9ce14fb25be9ba42d37b6bb61485c9a3ddd43cd3dde36b6087d8/coverage-7.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8f91bce78e32343af184c3b7fa28fcf5a9e2641f4b6623d392038f804939188", size = 254490, upload-time = "2026-07-15T18:55:06.889Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2c/42984561bc7f4c045dca67516a0c50ee5ef8d84352dbeb5559dc86c4823e/coverage-7.15.2-cp313-cp313-win32.whl", hash = "sha256:434e68d531858205895eb0d74b73d20b84260de426387d53c422a5acda2cf050", size = 223647, upload-time = "2026-07-15T18:55:08.941Z" }, + { url = "https://files.pythonhosted.org/packages/41/9f/39c7c9245efc583beddf89a87683574e663ed93637f3afb6cd7b88405676/coverage-7.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:26c3b04a6377fd7c09800921fa934e3a17c0020439cd59df73e73ae1d4b6a78c", size = 224190, upload-time = "2026-07-15T18:55:10.789Z" }, + { url = "https://files.pythonhosted.org/packages/c7/de/3a2883cf8a213659280ef4b403059e17a9acaeb7fc7fd4105e1226ff2e6d/coverage-7.15.2-cp313-cp313-win_arm64.whl", hash = "sha256:3ed010aa1b69cda8e827aabfca9866216c980e2dca82ab9a78c5f83689964c8b", size = 223583, upload-time = "2026-07-15T18:55:12.678Z" }, + { url = "https://files.pythonhosted.org/packages/81/5f/aed265fd7a3551a394f36dfe41868aee709b7f95db4052205b4ad1563ac3/coverage-7.15.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:40f633c5c5fc783732f6312280122e859538fa24461235597c13d803ea9a108a", size = 221650, upload-time = "2026-07-15T18:55:14.527Z" }, + { url = "https://files.pythonhosted.org/packages/6b/2c/222ba12a545189017120f8eddfc1a0bd4616b47d5d4a8d99421edb2fe4c6/coverage-7.15.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:075560438765b7a2ef43bf7aa7758661b53d889df47f062a31bda6c1ade553a2", size = 221988, upload-time = "2026-07-15T18:55:16.674Z" }, + { url = "https://files.pythonhosted.org/packages/aa/38/304b5877ab46e6c290b4292cfcf3fe28245f0e5597cad7f6acc91fc7e0a4/coverage-7.15.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:25fd15dd40a0a2c51a500d664ca29053c09c3259d998407bf982b6e114696138", size = 253029, upload-time = "2026-07-15T18:55:18.856Z" }, + { url = "https://files.pythonhosted.org/packages/6c/58/821b533b8db9e44cf1d8a97bd525149ced40dde1d0093da02cb78e715244/coverage-7.15.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b9a6367e4aff723e8ee8190836836124284e8fcd4265e307c844010cfa074f3f", size = 255536, upload-time = "2026-07-15T18:55:21.027Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f2/7aa06604c389d32ea7f0a6a988359a7eafc3cd3f8e7bc2e88cd2fdf0b877/coverage-7.15.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9854ca62c152874b2060772503535be2e8f53f70b8aaa7686b094888d872f984", size = 256881, upload-time = "2026-07-15T18:55:23.125Z" }, + { url = "https://files.pythonhosted.org/packages/a2/4f/1ef342339c7916d0096bc5888cc0f653882cc7bc8f897d5cb89143287c9b/coverage-7.15.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:913b6c56e110da40e035bbd168353bf7aaa2544a5eaccea5d98a4629aac156c7", size = 259196, upload-time = "2026-07-15T18:55:25.099Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f4/7ed055d7a9c5ec13b161773a115a5ccc6b0081d568c31fad830806306cc7/coverage-7.15.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aaccad4129d735a8a4d526f26929894c9a4e8ef7034566f210b176749d6906e3", size = 253036, upload-time = "2026-07-15T18:55:27.018Z" }, + { url = "https://files.pythonhosted.org/packages/14/79/ea82cca18c242a3a38b6c017da39726aa62dcb64aa635abf79b92009975c/coverage-7.15.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a164b50081fc7357331c4024ef4d17b78ba325f8380d05f5a69599a7e05257ee", size = 254887, upload-time = "2026-07-15T18:55:29.084Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ba/a136db3c0d9562b00e10b72540dbf3a33cd3bc5b95060c9308e247494623/coverage-7.15.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bfd341ccf78128e72c094bc70cc25b3ef309c33c7c2c66ba3ed4309549e02de1", size = 252852, upload-time = "2026-07-15T18:55:31.184Z" }, + { url = "https://files.pythonhosted.org/packages/17/17/ea334246b16b7d059953fad6fdefa11e33c68efbd3fe37b1098120a1fac2/coverage-7.15.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1473b3ba8e7ee0f076117b1a72c23f579a2b9e2bb742f48a8d86ea27ca93f91a", size = 257128, upload-time = "2026-07-15T18:55:33.163Z" }, + { url = "https://files.pythonhosted.org/packages/ed/c3/074fb66d46d607855f710876b117cbda562c5ab08363528e78820449f937/coverage-7.15.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:17c432b5f73ad52ef46fb06019f6fa7c66ce381961cf0f7dfd1d3a4bd3a98145", size = 252668, upload-time = "2026-07-15T18:55:35.063Z" }, + { url = "https://files.pythonhosted.org/packages/e1/c1/f620850ada9b36435921c9a3a8057013422b1d964eb4bf37fe138724d192/coverage-7.15.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:77f0ef5011df53a4bd1b35211ab122287f8d9b8d7aa1c4553e5c2deb24b1d446", size = 254325, upload-time = "2026-07-15T18:55:37.125Z" }, + { url = "https://files.pythonhosted.org/packages/cc/31/a729ca3689404493af82ef8e6ff70bd88bdda8da89aeef6ca9b387aeb2b4/coverage-7.15.2-cp314-cp314-win32.whl", hash = "sha256:f653e5d7248c1191ec988a85c72edeab46c3ff44f90639a4ed4874ec0be90243", size = 223844, upload-time = "2026-07-15T18:55:39.078Z" }, + { url = "https://files.pythonhosted.org/packages/c6/83/5d809dc808fb1698c671f3e372259bb9158e64b7ea526fc6ab7de64de9fe/coverage-7.15.2-cp314-cp314-win_amd64.whl", hash = "sha256:9911f31aad8906abe337c271343485cf20df5e70df5d2f57f9f136e7b55f26bc", size = 224331, upload-time = "2026-07-15T18:55:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/16/4e/35e488548e952795829e129995c4174df33bf432b591d1aa42c8d9e4e7ad/coverage-7.15.2-cp314-cp314-win_arm64.whl", hash = "sha256:e38def96ad59853824c97953fdcd2c320a84ba3ce99b417db78af8bb6c3db635", size = 223760, upload-time = "2026-07-15T18:55:43.518Z" }, + { url = "https://files.pythonhosted.org/packages/ed/49/dd2c86cd6374038f6e415fb5bfb86db5218553209c081384a020369dee79/coverage-7.15.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:835ec4e20b45f0a7f63ed78f94065aca00de033403df8377bfe8b9c6abc0a7be", size = 222384, upload-time = "2026-07-15T18:55:45.569Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/173ff17a1c0808e5a438f549f6f145d5ac7528f2791310b63523e3200ac7/coverage-7.15.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7466cc7ab6dc0db871d264bf99e8779f0917ee63d40730af0552f71535a6e072", size = 222647, upload-time = "2026-07-15T18:55:47.544Z" }, + { url = "https://files.pythonhosted.org/packages/84/f8/b8cba872162356fb44ac79c10309d987206a4461e32072fc29228dad7331/coverage-7.15.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e370c12133095ff18432de8c044962be85a5a96d90c6fcbce8e17e76236d2328", size = 264013, upload-time = "2026-07-15T18:55:49.768Z" }, + { url = "https://files.pythonhosted.org/packages/ee/67/a807a7586d0b8cae485308ddd55756f0806c92f8e0b411bacbf23c48edf3/coverage-7.15.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe41909c9515c3bfdb5f02c4d1f857dba322d9a9a1178069b91eea77889df63a", size = 266135, upload-time = "2026-07-15T18:55:51.941Z" }, + { url = "https://files.pythonhosted.org/packages/ce/67/cd78771dc985f7e4ebdcc82b1a96d9a932af9e806f01f2f91a89f4c72e80/coverage-7.15.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6aa28cfb6488e5453b5b762d65f73aa586380f6693a04d58078ce228a29b06c0", size = 268555, upload-time = "2026-07-15T18:55:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/18/3e/10134cf81275188c58568f324fc74aedff32c63ca4d5bbc513a91944a6f0/coverage-7.15.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcc0aae933921d03096f53b0b03eeb702129fd406dee59f08d2efacc68681fa5", size = 269674, upload-time = "2026-07-15T18:55:56.066Z" }, + { url = "https://files.pythonhosted.org/packages/75/4a/771b77de446cba985dc414bbc5844bd21604da05dbc044286df8318a48a7/coverage-7.15.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7c63387e21ab21f512c69c9756a8c7dadd322c7275edb064064433c9a09c3743", size = 263101, upload-time = "2026-07-15T18:55:58.107Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b5/70a7011da15f4071943361183aefa27847f3e3aec4fd335f1cb3d3a622b1/coverage-7.15.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e55510bc98ae943cece9e667a6c0fe94c6a92913720dea34243657a17993d0c", size = 266007, upload-time = "2026-07-15T18:56:00.468Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0d/f9547e804ce7ad49646ffeffac26699510efbe6c0f751b66fdc960c4e825/coverage-7.15.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2ff08701be2d1556fc78b326c80a3e8042da09352ecb3819105f8e386c8a3071", size = 263611, upload-time = "2026-07-15T18:56:02.615Z" }, + { url = "https://files.pythonhosted.org/packages/ac/59/f576a396659c0efd351f5c1544f67c3560e89c7761cabf7f65e412beeda5/coverage-7.15.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:38c9518b7103826c403a461544e3c2e77151e8676d06eaed85911a97e962584a", size = 267344, upload-time = "2026-07-15T18:56:04.622Z" }, + { url = "https://files.pythonhosted.org/packages/7c/5d/c2e4fce3579c0cb635024293f1a32bbe26df101b3e3a69f22243d1352b6c/coverage-7.15.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:dee88b1ed88587abd8c0269a1fc1f4cc77f7750d1dfde2869e2a123af420e67d", size = 262456, upload-time = "2026-07-15T18:56:06.641Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/956287d69436b66094bc4b57ac2da71e43bfd2a5524e958900b9f582fcf8/coverage-7.15.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2fbeeeecea279727f8ac16c8e1133ddfeee793e985c86ae343d6a5ce744eef8c", size = 264771, upload-time = "2026-07-15T18:56:08.795Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5a/6f979530c2734c575de77cf58f5f28d51f7123a94b5030fd9156fe5f363c/coverage-7.15.2-cp314-cp314t-win32.whl", hash = "sha256:cb0fddaa6884be6aae36ced9544b5e90f7d5f03845a2853bf47a14953a4e8688", size = 224151, upload-time = "2026-07-15T18:56:10.856Z" }, + { url = "https://files.pythonhosted.org/packages/54/7e/27f6b2a74d484742f4017553e710b01e396b23d809df3e95ca0bb9a2824b/coverage-7.15.2-cp314-cp314t-win_amd64.whl", hash = "sha256:77f091ea3a9cc611cd29f433565476bc1936c084ac8eee00ea0e7e70c27e4199", size = 224981, upload-time = "2026-07-15T18:56:12.928Z" }, + { url = "https://files.pythonhosted.org/packages/b1/48/284863423aa474240f6842bd00d680da22f4e6ea2e466618ef7c9c9e69a9/coverage-7.15.2-cp314-cp314t-win_arm64.whl", hash = "sha256:6fc448c377d6eeb00a47c673494bd9bae29280ca53987e1869e67ebedfe20658", size = 224294, upload-time = "2026-07-15T18:56:15.156Z" }, + { url = "https://files.pythonhosted.org/packages/ec/82/32e3bd191d498e64f6f911ad55d14006a0861e54869d2d32452326399e65/coverage-7.15.2-py3-none-any.whl", hash = "sha256:eb6bcae8d1a9d305351ecb108232441d11c5cfe9de840a04388ba5d2db8d735c", size = 213375, upload-time = "2026-07-15T18:56:17.305Z" }, +] + +[[package]] +name = "cryptography" +version = "48.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/45/870e7f4bef50e5f53b9f51d4428aee5290eedf58ba443f16b1ebb7ab8e66/cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a", size = 832989, upload-time = "2026-06-09T22:32:31.8Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/bc/ee4137cbbe105652c0ee4252792b78fc8e7afa4b8e61d9d5dc05a7f45731/cryptography-48.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3e4a1a3232eef2e6c732827d5722db29a0cc8b27af2a4d865b094cf954be9ca1", size = 8008324, upload-time = "2026-06-09T22:31:00.702Z" }, + { url = "https://files.pythonhosted.org/packages/d5/85/6379d42181bfc713094f081360fc5784d6c816b599d45e7f082502d173ce/cryptography-48.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:32143b24adb918f078134e1e230f1eb8cc04886b92c28b5f0041aaf3e5699225", size = 4696243, upload-time = "2026-06-09T22:32:33.446Z" }, + { url = "https://files.pythonhosted.org/packages/9c/87/c85d147b53323c7eb4d850920c8901377323c2a0ff8d79c262d4fee89aa2/cryptography-48.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0d27a5696721ef7a672b8c810f6aded391058e0b9486e63e6d93baf765da691", size = 4713235, upload-time = "2026-06-09T22:31:40.141Z" }, + { url = "https://files.pythonhosted.org/packages/79/58/67cbf8cf1ee7c54b439ca07bbecf8362c07afc11a3724fea70f745784add/cryptography-48.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb86ce1af36fe65041b6db9a8bb064ee621a7e5fded0f80d475ec243477cd242", size = 4702323, upload-time = "2026-06-09T22:31:42.191Z" }, + { url = "https://files.pythonhosted.org/packages/89/c6/24266ac10c47f6cd2a865f4446062b466da1d1f10b27189eac00e61bf0c9/cryptography-48.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b024e784ad6c077ee0147b35ea9cbfc1e34e1fd4c1dcca214c2794d73a12df08", size = 5300085, upload-time = "2026-06-09T22:31:58.703Z" }, + { url = "https://files.pythonhosted.org/packages/d2/bb/cc4b78784f97efc8c5874c2a9743708d172be6663024b34a0467885ae0c8/cryptography-48.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3752f2dbc8f07a30aad2932c986cea495b03bb554887828225da104f732852b6", size = 4746137, upload-time = "2026-06-09T22:31:31.01Z" }, + { url = "https://files.pythonhosted.org/packages/1f/52/0c44de3f5267f8fbe8e835138017522a333436166e406f0db9b9e6e3033f/cryptography-48.0.1-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:bd81490cd5801d755cf97bb68ac191f14b708470b1c7cf4580f669b9c9264cd8", size = 4333867, upload-time = "2026-06-09T22:32:28.096Z" }, + { url = "https://files.pythonhosted.org/packages/9a/2e/772d7adbfa931537bc401640b7cac9976bff689bda187833e5d63b428e49/cryptography-48.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:66fd0771e7b9c6dcd44cf1120690d2338d16d72795cf40cae2786a39eba65429", size = 4701805, upload-time = "2026-06-09T22:31:38.284Z" }, + { url = "https://files.pythonhosted.org/packages/f8/a3/b06844f303873493c963caf581c04df31c7035e0c1b0f02c4814d319ec80/cryptography-48.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:3fd2ca57062b241c856670b073487d2e86c4637937ca5601e48f97bf8e11fc8f", size = 5258461, upload-time = "2026-06-09T22:31:04.187Z" }, + { url = "https://files.pythonhosted.org/packages/9f/13/8b765e2e12b07c74941caadb9d1c8fdc006c4dfbf2b8f2d610519758954d/cryptography-48.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:0ee6ea481db1ab889cba043ec1eda17bb9c1ea79db6722f779c3667f9f70322f", size = 4745488, upload-time = "2026-06-09T22:32:30.07Z" }, + { url = "https://files.pythonhosted.org/packages/2e/aa/48972bce55049b32a94f4907eda4d75fa385aad8a39506cc2fc72196ecf0/cryptography-48.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f2ceef93cb096aa3c4cc4b5c94ca6131f9196d28c64d6111533402a9b2054d41", size = 4830256, upload-time = "2026-06-09T22:31:43.868Z" }, + { url = "https://files.pythonhosted.org/packages/47/a2/e5079a032fb85cf6005046ca92bbd78b0c82dad2b5751ab8c311659da06f/cryptography-48.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bd3f92d76217892b15df84ca256c2c113d386fdda7a7d8691aeeced976507c6", size = 4979117, upload-time = "2026-06-09T22:31:05.845Z" }, + { url = "https://files.pythonhosted.org/packages/b7/a0/8f50cae9c74e718ed769d63ed5c74bd0ea830c9550a74629cebd1b9c7bc7/cryptography-48.0.1-cp311-abi3-win32.whl", hash = "sha256:b9a32b876490d66c8bcc9963ef220199569748434ab01a9d6aaeabf88e7f5158", size = 3304154, upload-time = "2026-06-09T22:32:16.845Z" }, + { url = "https://files.pythonhosted.org/packages/c5/69/0572c77dbace6fef72f33755bd52ea399c71367250d366237f8691826b9e/cryptography-48.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:39489bfca54c7a1f6b297efcd8bc608ab92d16c4ca631b0cad4da46724588b24", size = 3817138, upload-time = "2026-06-09T22:32:00.388Z" }, + { url = "https://files.pythonhosted.org/packages/42/06/3e768b4c3bc78201583fa35a0e18f640dd782ff41afba88f8545481a8874/cryptography-48.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:f817adc181390bd54f2f700107a7419040fb7c1bdf2fc26f36551a06a68c3345", size = 7989830, upload-time = "2026-06-09T22:31:07.8Z" }, + { url = "https://files.pythonhosted.org/packages/8a/13/6476736484b94041110c8340a3eb63962fea4975baea8cb4a512adb44d4d/cryptography-48.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d5d30989c6917b478b5817902e85fddaea2261efa8648383d965381ccb9e1ac4", size = 4689201, upload-time = "2026-06-09T22:31:09.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/62/65a87f34d2a431546e2509b85d55e8c90df86d668f6731da64d538512ac2/cryptography-48.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:df637c05205ea7c1d7fbcbe54bbfea648a52951155f997af13d895d0ecc96991", size = 4702822, upload-time = "2026-06-09T22:32:24.409Z" }, + { url = "https://files.pythonhosted.org/packages/7f/59/810b5204b0a9b10f4b6bc06bd551a8b609803cd931806bc3b71884b225e5/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:869c3b8a53bfe27147832df48b32adadf558249d50e76cb3769d40e986b13265", size = 4694875, upload-time = "2026-06-09T22:32:08.737Z" }, + { url = "https://files.pythonhosted.org/packages/24/dc/d8ca05ffea724eec6d232ea6f18e74c269eb6bdfdcc9bfba689790d1325f/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:e361afba8918070d376df76f408a4f67fec0ee9cff81a99e48fe9a233ef59e17", size = 5290385, upload-time = "2026-06-09T22:31:15.212Z" }, + { url = "https://files.pythonhosted.org/packages/03/8c/3be6cb4da181f5bb6c19cf560c2359d60644a6b5fc5b57854e528f47b296/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d069066deead00ac7f090be101be875a06855908f7ec004c27b8fefb4acfb411", size = 4737082, upload-time = "2026-06-09T22:32:22.66Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f6/d5f60a5a1434dbfd949e227fd0065d194c7e6b6ac526b17f5c06152b8231/cryptography-48.0.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02", size = 4325328, upload-time = "2026-06-09T22:32:10.777Z" }, + { url = "https://files.pythonhosted.org/packages/17/b7/ba75dd947a14b6ad907b01ae8f6b5b348cdd1b48142f0063dee9e20c1d9d/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:15254441469dd6bf027039453288e2072124f8b6603563f5d759e1c9b69273fa", size = 4694530, upload-time = "2026-06-09T22:31:53.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/50d6b9e8aff12d8b67afaeb3569335e32dc83a5723e3bbded24fdac9f809/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:8ace4507d1e6533c125f4fac754f8bb8b6a74c08e92179dabd7e16571a3efbf3", size = 5245046, upload-time = "2026-06-09T22:31:25.774Z" }, + { url = "https://files.pythonhosted.org/packages/9f/04/618f4115cfc0add0838c82507aa18a346089428da8653ad38b3ff36f5cb3/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:b4e391975f038e66432328639620a4aff2d307513b004f1ca06d6225bced815c", size = 4736660, upload-time = "2026-06-09T22:32:12.676Z" }, + { url = "https://files.pythonhosted.org/packages/24/9c/06e062462a0de28a3b3911322eded4c16deb9f441b1b7575d3dc59488ab5/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42fcd8e26fe555d9b3577a135f5091fefa0aa4e99129c23fb56787a1bd4ada72", size = 4822229, upload-time = "2026-06-09T22:31:17.062Z" }, + { url = "https://files.pythonhosted.org/packages/f4/be/0561971eaaee4b8a0e7d5113c536921063ab91aaf23278ac374eaf881e11/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1400da5e32a43253392277eac7490a60e497d810a63dd5608d71bbd7af507c9", size = 4966364, upload-time = "2026-06-09T22:31:32.842Z" }, + { url = "https://files.pythonhosted.org/packages/a4/27/728c77876f12b000820b69ae490f3c4083775e79e07827e9e60be07ad209/cryptography-48.0.1-cp314-cp314t-win32.whl", hash = "sha256:0df56b056bc17c1b7d6821dfa65216e62bd232d8ab05eb3db44e71d235651471", size = 3278498, upload-time = "2026-06-09T22:31:29.154Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/79a612c6d7b1e6ee0edd43633d53035bec2cfb78c82b76f7864f39e36f34/cryptography-48.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9de21387aa95e2a895823d0745b430bed4f33503ba9ab5e0b5311f33e37d66d2", size = 3798790, upload-time = "2026-06-09T22:31:56.697Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6c/00fa2a95997164c8b2072ce327c23d4ab20809ccc323ea5fab91e53a4bba/cryptography-48.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:4fdc69f8e4316bcf0c8c8ec1f26f285d12e8142d88d96c876a59a03be3f6ae67", size = 7987408, upload-time = "2026-06-09T22:32:20.777Z" }, + { url = "https://files.pythonhosted.org/packages/b0/d9/45f309a7e4e5f3f8f121d6d3be9e94024a7726ec598d6e08ae04edb2f04d/cryptography-48.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48fe40804d4caa2288f24e70ca8c64c42dd826da0ad7e4f1b41b2128d679e6c8", size = 4690196, upload-time = "2026-06-09T22:31:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/5f/9f/a1bc8bcc798811b8527eb374bbccf30a3f3e806829d967118222bf1125eb/cryptography-48.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:86be3b1b0b6bf09482fb50a979c508d2950ed95f5621ec77f4e385962006b83a", size = 4696782, upload-time = "2026-06-09T22:31:45.615Z" }, + { url = "https://files.pythonhosted.org/packages/66/c2/81a4fb4e4373c500bb526bc337ac5719dd31dd15b970b84a238168c6aa08/cryptography-48.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4ab0a343c807bbcd90c971cd1ecf072937cd01847a9e002bef88fb47ac6be577", size = 4696618, upload-time = "2026-06-09T22:31:11.564Z" }, + { url = "https://files.pythonhosted.org/packages/e5/0b/aa68b221dde92d09cb29a024ede17550ee21e77a404e59fc093c82bb51e1/cryptography-48.0.1-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9621de99d2da096006b629979efd8ae7eb2d8b822488d0c89ee4000c306c59b1", size = 5289970, upload-time = "2026-06-09T22:31:20.368Z" }, + { url = "https://files.pythonhosted.org/packages/78/13/fba657f958d2af66ea959a4ba01212632089249d34af1ae48054136344d7/cryptography-48.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:88c852a0ae366e262e5a1744b685e6a433dc8788dd2a277e418bf4904203609d", size = 4731873, upload-time = "2026-06-09T22:31:22.253Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4c/9a964756d24a26b3e34dfcb16f961b89838786e6700b635b0d1e3adff4b6/cryptography-48.0.1-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:43c5835e2cb98c8733d86f57d6fc879b613f5c3478607281c3e36daffc6dd8a6", size = 4330804, upload-time = "2026-06-09T22:31:36.56Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0f/a10f3a6eb12950a10e3a874070283aa2dd5875b2bfd15fad8a3e17b3f13e/cryptography-48.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46", size = 4696217, upload-time = "2026-06-09T22:31:13.351Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6f/5cd12f951165ea73ef85266775d97e4c763b2474ccfd816dd69d3a18d6f8/cryptography-48.0.1-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:b7a2d1a937a738a881737cec135a38bb61470589b17515b9f73f571d0ae10401", size = 5245252, upload-time = "2026-06-09T22:32:02.193Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/8aaa12e4516ec4464033ab79b6f3b592bd5a92102467c4ace8a0d970203f/cryptography-48.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b74ca3b8e5ecdd833bf6a002ca41b4793bb27fb8f1c06ffaf2643c9e9140e31b", size = 4731388, upload-time = "2026-06-09T22:32:04.019Z" }, + { url = "https://files.pythonhosted.org/packages/1b/24/50027ea4dca85ec1f40688f3c24fb32ccacd520583c9592c3cc95628e6fb/cryptography-48.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2c37f2461406063b417837f5f3daab668652acd82423efcd7f0a9f04be972de1", size = 4824186, upload-time = "2026-06-09T22:32:18.707Z" }, + { url = "https://files.pythonhosted.org/packages/52/41/04cb5eb17085ade6f50cc611fb657df6a0f5885350de8764ece89c050197/cryptography-48.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:86fe77abb1bd87afb251d4d02ada7ecf53a32cee9b67d976abb2e45a13297475", size = 4964539, upload-time = "2026-06-09T22:31:18.793Z" }, + { url = "https://files.pythonhosted.org/packages/36/bf/ed70785c496e89d7e73b7cda2d21f2447fd6d4e821714b8d04ff217fed92/cryptography-48.0.1-cp39-abi3-win32.whl", hash = "sha256:6b2c0c3e6ccf3ade7750f836ef3ee36eea250cc467d45c256895573ac08cc6f1", size = 3282307, upload-time = "2026-06-09T22:30:53.162Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ff/371ea7d252656ee1eb6d83eeeef3d1d0c6baf1d6497687d081ea03814670/cryptography-48.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:9a49ca6c81417f6a5edb50375a60cccdd70fa0a91a5211829dbea74eba94d2ac", size = 3793408, upload-time = "2026-06-09T22:32:15.191Z" }, +] + +[[package]] +name = "cyclonedx-python-lib" +version = "11.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "license-expression" }, + { name = "packageurl-python" }, + { name = "py-serializable" }, + { name = "sortedcontainers" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/c9/5d0ccdd19bc7d8ab803b90695c1706aa2ea8529685d18e682dc2524d2630/cyclonedx_python_lib-11.11.0.tar.gz", hash = "sha256:4b3194db72b613717f2912447e67ab618c75ff7dcac6c4af3c0e9e1ac617c102", size = 1442983, upload-time = "2026-06-17T11:57:49.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/f3/56ccb2884aaa3db5622368e5191a3384b15f35392aa93df8b2f508c660d2/cyclonedx_python_lib-11.11.0-py3-none-any.whl", hash = "sha256:3049fc83e06a059b5c5907a527625a8ed5073caab10607ed4c9e5503b590fd44", size = 528689, upload-time = "2026-06-17T11:57:47.358Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "fastapi" +version = "0.139.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/95/d3f0ae10836324a2eab98a52b61210ac609f08200bf4bb0dc8132d32f78a/fastapi-0.139.2.tar.gz", hash = "sha256:333145a6891e9b5b3cfceb69baf817e8240cde4d4588ae5a10bf56ffacb6255e", size = 423428, upload-time = "2026-07-16T15:06:17.912Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/c7/cb03251d9dfb177246a9809a76f189d21df32dbd4a845951881d11323b7f/fastapi-0.139.2-py3-none-any.whl", hash = "sha256:b9ad015a835173d59865e2f5d8296fbc2b317bf56a2ba1a5bfbdd03de2fd4b1c", size = 130234, upload-time = "2026-07-16T15:06:19.557Z" }, +] + +[[package]] +name = "filelock" +version = "3.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/9f/994e80905542b748eb5b9f36d71458f0aea51a7be0fcb52ad959787dc1b7/filelock-3.31.0.tar.gz", hash = "sha256:c188cbc4307c18894c5424fa73f97ea7fa127ddf62192487546da3a214d0a381", size = 180931, upload-time = "2026-07-18T05:53:29.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/4a/e213905d3b8ad3d35d14fc056b36134a274e7f6a1050e94428b5be10a94c/filelock-3.31.0-py3-none-any.whl", hash = "sha256:739b73e580fe88bb78d830aeddbc492519ece3d97ac8368de13a2032c61010c1", size = 96080, upload-time = "2026-07-18T05:53:27.732Z" }, +] + +[[package]] +name = "greenlet" +version = "3.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/f1/fbbfef6af0bad0548f09bc28948ea3c275b4edb19e17fc5ca9900a6a634d/greenlet-3.5.3.tar.gz", hash = "sha256:a61efc018fd3eb317eeca31aba90ee9e7f26f22884a79b6c6ec715bf71bb62f1", size = 200270, upload-time = "2026-06-26T19:28:24.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/6e/4c37d51a2b7f82d2ff11bb6b5f7d766d9a011726624af255e843727627a3/greenlet-3.5.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:719757059f5a53fd0dde23f78cffeafcdd97b21c850ddb7ca684a3c1a1f122e2", size = 288685, upload-time = "2026-06-26T18:22:08.977Z" }, + { url = "https://files.pythonhosted.org/packages/7a/73/815dd90131c1b71ebdf53dbc7c276cafec2a1173b97559f97aba72724a87/greenlet-3.5.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:efa9f765dd09f9d0cdac651ffdf631ee59ec5dc6ee7a73e0c012ba9c52fbdf5b", size = 604761, upload-time = "2026-06-26T19:07:10.114Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/079cfe76bcef36b153b25607ee91c6fcb58f17f8b23c86bbbeabe0c88d72/greenlet-3.5.3-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7faba15ac005376e02a0384504e0243be3370ce010296a44a820feb342b505ab", size = 617044, upload-time = "2026-06-26T19:10:07.25Z" }, + { url = "https://files.pythonhosted.org/packages/fb/fb/d97dc261209c80744b7c8132693a30d70ec6e7315e632cb0a10b3fec94dd/greenlet-3.5.3-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5795cd1101371140551c645f2d408b8d3c01a5a29cf8a9bce6e759c983682d23", size = 622351, upload-time = "2026-06-26T19:24:16.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/87/b4d095775a3fb1bcafbb483fc206b27ebb785724c83051447737085dc54e/greenlet-3.5.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:87142215824be6ac05e2e8e2786eec307ccbc27c36723c3881959df654af6861", size = 614244, upload-time = "2026-06-26T18:32:17.594Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ac/e5fee13cbbd0e8de312d9a146584b8a51891c68847330ef9dc8b5109d23f/greenlet-3.5.3-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:af4923b3096e26a36d7e9cf24ab88083a20f97d191e3b97f253731ce9b41b28c", size = 425395, upload-time = "2026-06-26T19:25:37.144Z" }, + { url = "https://files.pythonhosted.org/packages/8a/70/7559b609683650fa2b95b8ab84b4ab0b26556a635d19675e12aa832d826d/greenlet-3.5.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215275b1b49320987352e6c1b054acca0064f965a2c66992bed9a6f7d913f149", size = 1574210, upload-time = "2026-06-26T19:09:03.077Z" }, + { url = "https://files.pythonhosted.org/packages/ae/73/be55392074c60fc37655ca40fa6022457bfbf6718e9e342a7b0b41f96dd2/greenlet-3.5.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6b1b0eed82364b0e32c4ea0f221452d33e6bb17ae094d9f72aed9851812747ea", size = 1638627, upload-time = "2026-06-26T18:31:44.748Z" }, + { url = "https://files.pythonhosted.org/packages/14/40/c57489acf8e37d74e2913d4eff63aa0dba17acccc4bdeef874dde2dbbec9/greenlet-3.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:cde8adafa2365676f74a979744629589999093bc86e2484214f58e61df08902c", size = 239882, upload-time = "2026-06-26T18:23:27.518Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/6fea0e3d6600f785069481ee637e09378dd4118acdfd38ad88ae2db31c98/greenlet-3.5.3-cp312-cp312-win_arm64.whl", hash = "sha256:c4e7b79d83805475f0102008843f6eb45fd3bb0b2e88c774adab5fbaab27117d", size = 238211, upload-time = "2026-06-26T18:22:37.671Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ff/a620267401db30a50cc8450ee90730e2d4a85658c055c0e760d4ed47fb13/greenlet-3.5.3-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:c8d87c2134d871df96ecdea9cec7cbaab286dadab0f56476e57aaf9e8ac11550", size = 287609, upload-time = "2026-06-26T18:21:14.724Z" }, + { url = "https://files.pythonhosted.org/packages/d6/fa/5401ac78021c826a25b6dde0c705e0a8f29b617509f9185a31dac15fbe1b/greenlet-3.5.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2d185dd1621757e70c3861cceffd5317ab4e7ed7eb09c82994828468527ade5", size = 607435, upload-time = "2026-06-26T19:07:11.412Z" }, + { url = "https://files.pythonhosted.org/packages/e9/76/1dc144a2e56e65d36405078ed774224375ea520a1870a6e46e08bb4ac7bf/greenlet-3.5.3-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1c514a468149bf8fbbab874188a3535cd8a48a3e353eb53a3d424296f8dbacd3", size = 619787, upload-time = "2026-06-26T19:10:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/57/61/2f5b1adf256d039f5dab8005de8d3d7ad2b0070a3219c0e036b3fbfeb440/greenlet-3.5.3-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9ad04dd75458c6300b047c61b8639092433d205a25a14e310d6582a480efcca1", size = 625580, upload-time = "2026-06-26T19:24:18.344Z" }, + { url = "https://files.pythonhosted.org/packages/bf/87/c298cee62df1de4ad7fec32abda73526cff347fd143a6ed4ac369246668a/greenlet-3.5.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:915f887cf2682b66419b879423a2e072634aa7b7dce6f3ada4957cfced3f1e9a", size = 616786, upload-time = "2026-06-26T18:32:19.128Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/ab7fc9e543e44d6879b0a6ef9a4b2188940fd180cc65d6f646883ddf7201/greenlet-3.5.3-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:afaabdd554cd7ae9bbb3ca070b0d7fdfd207dbf1d16865f7233837709d354bda", size = 427933, upload-time = "2026-06-26T19:25:38.219Z" }, + { url = "https://files.pythonhosted.org/packages/9e/2e/e6f009885ed0705ccf33fe0583c117cfd03cde77e31a596dd5785a30762b/greenlet-3.5.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:766cfd421c13e450feb340cd472a3ed9957d438727b7b4593ad7c76c5d2b0deb", size = 1574316, upload-time = "2026-06-26T19:09:04.273Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fe/43fd110b01e40da0adb7c90ac7ea744bef2d43dca00de5095fd2351c2a68/greenlet-3.5.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2ecda9ec22edf38fa389369eaed8c3d37c05f3c54e69f69438dbb2cc1de1458b", size = 1638614, upload-time = "2026-06-26T18:31:46.297Z" }, + { url = "https://files.pythonhosted.org/packages/0f/7c/062447147a61f8b4337b156fe70d32a165fcf2f89d7ca6255e572806705c/greenlet-3.5.3-cp313-cp313-win_amd64.whl", hash = "sha256:c82304750f057167ff60d188df1d0cc1764ce9567eadf03e6a7443bcedd0b30b", size = 239850, upload-time = "2026-06-26T18:21:54.613Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7e/220a7f5824a64a60443fc03b39dfac4ea63a7fb6d481efa27eafa928e7f4/greenlet-3.5.3-cp313-cp313-win_arm64.whl", hash = "sha256:dc133a1569ee667b2a6ef56ce551084aeefd87a5acbc4736d336d1e2edc6cfc4", size = 238141, upload-time = "2026-06-26T18:22:48.507Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/43e116ee114b28737ba7e12952a0d4e2f55944d0f84e42bc91ba7192a3c9/greenlet-3.5.3-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:fd2e02fa07485778536a036222d616ab957b1d533f36b3ed98ce725d9c9d3117", size = 288202, upload-time = "2026-06-26T18:23:49.604Z" }, + { url = "https://files.pythonhosted.org/packages/82/2f/146d218299046a43d1f029fd544b3d110d0f175a09c715c7e8da4a4a345d/greenlet-3.5.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df0a0628d1597eb0897b62f55d1343f772405fd25f3b2a796c76874b0c2e22e8", size = 654096, upload-time = "2026-06-26T19:07:12.71Z" }, + { url = "https://files.pythonhosted.org/packages/a0/cc/04738cafb3f45fa991ea44f9de94c47dcec964f5a972300988a6751f49d9/greenlet-3.5.3-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ebd933a6adabc298bab47731a130fe6bfb888bd934eee37810f151159544540d", size = 666304, upload-time = "2026-06-26T19:10:09.503Z" }, + { url = "https://files.pythonhosted.org/packages/86/a9/73fa62893d5b84b4205544e6b673c654cc43aa5b9899bac00f04d64af73d/greenlet-3.5.3-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8d19fe6c39ebff9259f07bcc685d3290f8fa4ea2278e51dd0008e4d6b0f2d814", size = 670657, upload-time = "2026-06-26T19:24:19.967Z" }, + { url = "https://files.pythonhosted.org/packages/ce/aa/4e0dad5e605c270c784ab911c43da6adb136ccd4d81180f763ca429a723d/greenlet-3.5.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b9d501b40e80b70e32323c799dd9b420a5577a9601469d362ae1ffb690f3a7c", size = 663635, upload-time = "2026-06-26T18:32:20.802Z" }, + { url = "https://files.pythonhosted.org/packages/29/7e/2ffce64929fb3cab7b65d5a0b20aaf9764e227681d731b041077fc9a525a/greenlet-3.5.3-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:962c5df2db8cb446da51edf1ca5296c389d93b99c9d8aa2ee4c7d0d8f1218260", size = 473497, upload-time = "2026-06-26T19:25:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/d1/50/13efdbea246fe3d3b735e191fec08fb50809f53cd2383ebe123d0809e44b/greenlet-3.5.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a1fad1d11e7d6aab184107baa8e4ece11ccba3ec9599cd7efa5ff4d70d43256a", size = 1621252, upload-time = "2026-06-26T19:09:05.647Z" }, + { url = "https://files.pythonhosted.org/packages/f7/22/c0a336ae4a1410fd5f5121098e5bfbf1865f64c5ef80b4b5412886c4a332/greenlet-3.5.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fad5aec764399f1b5cc347ad250a59660f20c8f8888ea6bae1f93b769cce1154", size = 1684824, upload-time = "2026-06-26T18:31:47.738Z" }, + { url = "https://files.pythonhosted.org/packages/7a/94/91aec0030bea75c4b3244251d0de60a1f3432d1ecb53ab6c437fb5c3ba61/greenlet-3.5.3-cp314-cp314-win_amd64.whl", hash = "sha256:7669aa24cf2a1041d6f7899575b494a3ab4cf68bfcc8609b1dc0be7272db835e", size = 240754, upload-time = "2026-06-26T18:22:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/e5/06/68d0983e79e02138f64b4d303c500c27ddb48e5e77f3debb80888a921eae/greenlet-3.5.3-cp314-cp314-win_arm64.whl", hash = "sha256:5b4807c4082c9d1b6d9eed56fcd041863e37f2228106eef24c30ca096e238605", size = 239549, upload-time = "2026-06-26T18:22:42.996Z" }, + { url = "https://files.pythonhosted.org/packages/91/95/3e161213d7f1d378d15aa9e792093e9bfe01844680d04b7fd6e0107c9098/greenlet-3.5.3-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:271a8ea7c1024e8a0d7dd2be66dd66dda8a07193f41a17b9e924f7600f5b62be", size = 296389, upload-time = "2026-06-26T18:22:20.657Z" }, + { url = "https://files.pythonhosted.org/packages/00/92/715c44721abe2b4d1ae9abde4179411868a5bff312479f54e105d372f131/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19131729ae0ddc3c2e1ef85e650169b5e37ee32e400f215f78b94d7b0d567310", size = 653382, upload-time = "2026-06-26T19:07:14.209Z" }, + { url = "https://files.pythonhosted.org/packages/a0/83/37a10372a1090a6624cca8e74c12df1a36c2dc36429ed0255b7fb1aeee23/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1540dd8e5fc2a5aec40fbb98ef8e149fa47c89a4b4a1cf2575a14d3d1869d7a8", size = 659401, upload-time = "2026-06-26T19:10:10.876Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/8faec206b851c22b1733545fda900829a1f3f5b1c78ae7e0fb3dba57d9f4/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b897d97759425953f69a9c0fac67f8fe333ec0ce7377ef186fb2b0c3ad5e354d", size = 659582, upload-time = "2026-06-26T19:24:21.357Z" }, + { url = "https://files.pythonhosted.org/packages/db/e2/d1509cad4207da559cc42986ecdd8fc67ad0d1bba2bf03023c467fd5e0f3/greenlet-3.5.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e81fa194a1d20967877bdf9c7794db2bc99063e5be36aee710c08f04c5bb087f", size = 656969, upload-time = "2026-06-26T18:32:22.272Z" }, + { url = "https://files.pythonhosted.org/packages/b4/55/50c19e49f8045834ada71ef12f8ad048eba8517c6aa41161bed676328fae/greenlet-3.5.3-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:3236754d423955ea08e9bb5f6c04a7895f9e22c290b66aa7653fcb922d839eb0", size = 491037, upload-time = "2026-06-26T19:25:40.672Z" }, + { url = "https://files.pythonhosted.org/packages/86/7d/eaf70de20aadca3a5884aec58362861c64ce45e7b277f47ed026926a3b89/greenlet-3.5.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:55cf4d777485d43110e47133cbba6d74a8885a87ec1227ef0267f9ee80c5aa21", size = 1617822, upload-time = "2026-06-26T19:09:06.893Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f9/414d38fc400ae4350d4185eaad1827676f7cf5287b9136e0ed1cbbe20a7f/greenlet-3.5.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:12a248ba75f6a9a236375f52296c498c89ff1d8badf32deb9eca7abd5853f7da", size = 1677983, upload-time = "2026-06-26T18:31:49.396Z" }, + { url = "https://files.pythonhosted.org/packages/e4/15/7edb977e08f9bff702fe42d6c902702786ff6b9694058b4e6a2a6ac90e57/greenlet-3.5.3-cp314-cp314t-win_amd64.whl", hash = "sha256:efc6bd60ea02e085862c74a3ef64b147ffc6f1a5ea7d9f26e7a939943f68c1e3", size = 243626, upload-time = "2026-06-26T18:24:41.485Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httptools" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/e5/d471fcb0e14523fe1c3f4ba58ca52480e7bd70ad7109a3846bc75892f7fb/httptools-0.8.0.tar.gz", hash = "sha256:6b2a32f18d97e16e90827d7a819ffa8dbd8cc245fc4e1fa9d1095b54ef4bd999", size = 271342, upload-time = "2026-05-25T22:17:48.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/88/1d21a36da8f5cb0fa49eafd4b169eba5608d57e75bbcf61845cbc6243216/httptools-0.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:880490234c10f70a9830743097e8958d6e4b9f5a0ffc24515023afeef984054d", size = 208247, upload-time = "2026-05-25T22:17:07.843Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/cc4feea2945cb3051038f090c9b36bd5b8a9d7f5a894a506a8983e33fd1c/httptools-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5931891fb7b441b8a3853cf1b85c82c903defce084dd5f6771ca46e31bf862c5", size = 113064, upload-time = "2026-05-25T22:17:09.136Z" }, + { url = "https://files.pythonhosted.org/packages/e3/a6/febbb8b8db0f58b38e44ad6cb946e6a255ae49b55f2e8543408fb7501ccd/httptools-0.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b15fc622b0f869d19207c4089a501d9bcc63ca5e071ffdd2f03f922df882dcb2", size = 523851, upload-time = "2026-05-25T22:17:10.106Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e4/f90a0df0b83beff265b7e3b65f2a4cefd95792d4be0ac3e16049f2acd3c2/httptools-0.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:425f83884fd6343828d8c565f046cb72b6d19063f6924093e11bcd8e1548cd09", size = 518842, upload-time = "2026-05-25T22:17:11.218Z" }, + { url = "https://files.pythonhosted.org/packages/9e/2d/0c9ac76dd2c893841fbf6498d6acec4f2442e1b7067f6e3e316a80e494e8/httptools-0.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ef7c3c97f4311c7be57e2986629df89d49cb434dbff78eafcd48c2bff986b15a", size = 501238, upload-time = "2026-05-25T22:17:12.728Z" }, + { url = "https://files.pythonhosted.org/packages/ca/42/906adc91ae3a5fa9c59c0a2f21c139725bd7e5b41ae6acd485cd14123ebf/httptools-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a1afd7c9fbff0d9f5d489c4ce2768bd09c84a46ddefc7161e6aa82ae35c85745", size = 509567, upload-time = "2026-05-25T22:17:13.842Z" }, + { url = "https://files.pythonhosted.org/packages/05/0b/4240efeb672751ee5b9b380cb0e3fdc050bc05f68adc7a8aefc4fcd9a69a/httptools-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd96f29b4bab1d42fa6e3d008711c75e0f79e94e06827330160e3a304227f150", size = 90918, upload-time = "2026-05-25T22:17:15.155Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e5/8cfcabc5546e8022f168be28bcdaa128a240a0befdd03b59d558b4f18bd6/httptools-0.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:614ceea8ea606848bece2338ac03b3ce5324bcb4be8dc7d377ed708012fa4db8", size = 205148, upload-time = "2026-05-25T22:17:16.333Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0e/0fb14848c19a686c8062ff9067c1a48793e3224b47bc5b201535b6036fce/httptools-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2d689918c15a013c65ef52d9fd495d766893ab831a2c8d89f2ac5940a5df847c", size = 111368, upload-time = "2026-05-25T22:17:17.586Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1b/46f1cecf06b9bbde8e4b8c88034ac7908989e5ff7a3a388ef38392949c1f/httptools-0.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb3028cca2fc0a6d720e52ef61d8ebb62fcbfeb1de56874546d858d3f25a26b7", size = 486447, upload-time = "2026-05-25T22:17:18.564Z" }, + { url = "https://files.pythonhosted.org/packages/77/00/258bfc0837221f81d9725c45f9b948a6a6b2994a147a4fb66e85100c668f/httptools-0.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:88bdd940f2b5d487b4d032c6afa5489a7dc4694410d43de3c38c4fb3af0dc45d", size = 482448, upload-time = "2026-05-25T22:17:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/04/ab/d1cef3b5523f4d272a70f42a776c3169a2dddfe3a54de4b2ce4a36341528/httptools-0.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a43c9dd399758ccc0531acb0a3c4a6c299ee893ee9400e9c893b7bdcfae0681", size = 464460, upload-time = "2026-05-25T22:17:20.882Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/5d1d072442277bb2b3434e0e60690b8e8c23840ef7de8b6ea54040a536d3/httptools-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0770728beb05094c809b98e814edff5fef69d26ad7d21185f2f6d5884a0ba683", size = 471312, upload-time = "2026-05-25T22:17:22.085Z" }, + { url = "https://files.pythonhosted.org/packages/0d/66/b96623b27e51a68199ef4efdda0613cced9233fe3062ac74e50749c5ad37/httptools-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:7685df791fad561384bfb139e77fde27a1ffd93134e016f95a0db424ffbf77b1", size = 90117, upload-time = "2026-05-25T22:17:23.074Z" }, + { url = "https://files.pythonhosted.org/packages/1a/12/fa3fbf5f9517b273edea2dc982aa82a8c634091e67c590792b729017bc6f/httptools-0.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:de242a49b5d18e0a8776e654e9f6bf6d89f3875a5c35b425a0e7ce940feb3fd6", size = 206183, upload-time = "2026-05-25T22:17:24.004Z" }, + { url = "https://files.pythonhosted.org/packages/30/fc/5e7c4cb443370f2090a3aba0453a07384d29ff66b7435bb90e77e1037599/httptools-0.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:159e9ab5f701ccd42e555a12f1ad8ff69702910fc1c996cf2bb66e5fcb7a231b", size = 112079, upload-time = "2026-05-25T22:17:25.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/53/771bd891eb0f236f32145d6a1775777ec85745f3cc983a1f23d1a3b8ddfe/httptools-0.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c4a9f1707e4823d54dfec6c33fa3697d302aed536ed352a7ebb5a061ddb869d0", size = 481596, upload-time = "2026-05-25T22:17:26.186Z" }, + { url = "https://files.pythonhosted.org/packages/62/42/94e15bc68ce3d423243c45d7f1b0c7561f13844f97dc52ae23182fb65628/httptools-0.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d76ad7b951387e3632c8716a9bb03ac5b45c5f16119aa409db0459520887944e", size = 480865, upload-time = "2026-05-25T22:17:27.542Z" }, + { url = "https://files.pythonhosted.org/packages/1c/7c/fe2980fc03723272e30f135b62360b075f513dfe7cc73aef36c7f04012bd/httptools-0.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a3b7387147361c3fd47a0bde763c5c91b5b4cd4dc9989b8ece84ff436c99843b", size = 463189, upload-time = "2026-05-25T22:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/47fc5fff68acd1bfa20b4734059c9a06cadb88119dcd5258b5b0d21d91c8/httptools-0.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0", size = 466610, upload-time = "2026-05-25T22:17:29.816Z" }, + { url = "https://files.pythonhosted.org/packages/60/bd/07b13c93ffd9bec9546e0d43f8e19378dd696dbd278511406bc07371ef1f/httptools-0.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:19d1ee275bb59ba2643ba9a3a1e51cc0c788caf2b8df506368e03f56fdd08527", size = 92705, upload-time = "2026-05-25T22:17:31.133Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c4/121648f68ce066d7bd762d6b6d97e620847642d38d54f3d90ff11d947629/httptools-0.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:de1ed58a974e75d56560acc7e7fed01a454994429456f65209789992e41f2568", size = 215023, upload-time = "2026-05-25T22:17:32.401Z" }, + { url = "https://files.pythonhosted.org/packages/b9/b0/312a062ae741ae3e8baa8c8bf20be81b2e67337b259ab4349bebc7b6142e/httptools-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e93c227b595c6926c1acee96891dd9da4be338cfbe82e5cd3bb9d8dd7dc4ac0b", size = 117405, upload-time = "2026-05-25T22:17:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/fc/37/fccd705f795386bb05bf413012fecff2a33e5aa8c2f069096de3e9fd8702/httptools-0.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2a021c3a8e65cc125390d72f59b968afca3bdcaff25bd67965e0a055a14946ca", size = 558497, upload-time = "2026-05-25T22:17:34.732Z" }, + { url = "https://files.pythonhosted.org/packages/bd/39/f172e8003576de35f5ba77ff417cf0e34429d35dc014deef15afa337a72c/httptools-0.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48774d39cbb70e2b1f71f88852a3087ae1d3a1eb80482bb48c13067ab080c14f", size = 571585, upload-time = "2026-05-25T22:17:35.813Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b9/f5564760af99f3dbbf3f9104dc00e5da27e96cf433c6bdcf77617f70bf3f/httptools-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:88eead8ec8680a9f146c655bc88445a325bd7921cfd8194c7337e9467282427d", size = 543297, upload-time = "2026-05-25T22:17:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/99/67/8d9f2c313618e161b82f3873188e7196126da1d6e29688df40eb3997c77a/httptools-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c032fa028f46871ec7e1fc59fc15e8023eab3e6bbe6ece786a1611719a5d081", size = 539535, upload-time = "2026-05-25T22:17:38.032Z" }, + { url = "https://files.pythonhosted.org/packages/48/63/b906c01e53f50d432c0defe43ce52764a111dc1bdd028bafbeb54dcfd008/httptools-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:384c17174464c8e873398b7af24f0b1f44d992c820328413951a625323155d77", size = 108209, upload-time = "2026-05-25T22:17:39.473Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "librt" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/2f/3908645ddddab7120b46295e541ead308109fa48dbec7d67d7a778870d60/librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781", size = 211402, upload-time = "2026-07-08T12:26:29.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/f4/b2933ddae222dac338476abb872641169a5cfed2c2bb5444a5b07b32b0c3/librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0", size = 150990, upload-time = "2026-07-08T12:25:02.42Z" }, + { url = "https://files.pythonhosted.org/packages/90/ef/db98f744ca50e6efc9c95c70ee49b77aefac31f6a3fc7c83754a42d6a74f/librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5", size = 155238, upload-time = "2026-07-08T12:25:03.681Z" }, + { url = "https://files.pythonhosted.org/packages/03/e7/a197e7bc72baf2c61ce7fdc6906a5054dc05bd8da0819aa894e4857bf87e/librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9", size = 503073, upload-time = "2026-07-08T12:25:05.049Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e7/7887712e27da7c1ab80fcabb1de6eb24243964f6557cae530d4b70706dbd/librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b", size = 496528, upload-time = "2026-07-08T12:25:06.26Z" }, + { url = "https://files.pythonhosted.org/packages/94/f0/f2283385bb6b950b26a1410f4ce51ec27231e0b3a4b925c46366d218b198/librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03", size = 531786, upload-time = "2026-07-08T12:25:07.658Z" }, + { url = "https://files.pythonhosted.org/packages/36/11/69ac3b54766ffba5fd7e5acebfb048d66dbe1f9f2d14516c2b3edc59cf87/librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e", size = 524393, upload-time = "2026-07-08T12:25:09.121Z" }, + { url = "https://files.pythonhosted.org/packages/61/5f/d72f95fd444a926a3c14b4e24979474116988dd57a45be242077c45d3c22/librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd", size = 543026, upload-time = "2026-07-08T12:25:10.459Z" }, + { url = "https://files.pythonhosted.org/packages/c4/08/dcd9993ad192737a004ba263d549f8ea605b326b952e7d6205c7d4170b76/librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348", size = 546829, upload-time = "2026-07-08T12:25:11.716Z" }, + { url = "https://files.pythonhosted.org/packages/96/d5/6d9bb2f54e4109a956b7128836529653eb9d740f784bc47ed10a02c1000e/librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7", size = 535700, upload-time = "2026-07-08T12:25:13.144Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f2/10946922503858a359492fa27f13e86228bde702116a740ac7b3cd185f24/librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82", size = 573566, upload-time = "2026-07-08T12:25:14.336Z" }, + { url = "https://files.pythonhosted.org/packages/48/a8/94f00e3c99479a18088af3685ea016c42f3c7d5d1964d8dbb40c08d7f1aa/librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3", size = 106099, upload-time = "2026-07-08T12:25:16.159Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7b/2da9c74c1ed25a89cc4e1c8e007ea2eb4a0f1fafa3e70d757fe3242c5c5c/librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa", size = 126934, upload-time = "2026-07-08T12:25:17.275Z" }, + { url = "https://files.pythonhosted.org/packages/d0/65/aead61bbf3b5358593f9d4779d2a0e88eaf6ec191a6342dde36dd1df6371/librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1", size = 112236, upload-time = "2026-07-08T12:25:18.425Z" }, + { url = "https://files.pythonhosted.org/packages/67/3b/18e7b63255297a2bdc9c25c8d6d4ca8eca9f63aceb1252c0f7427ac7099e/librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3", size = 151027, upload-time = "2026-07-08T12:25:19.638Z" }, + { url = "https://files.pythonhosted.org/packages/4d/68/e2248452c00d1a03b45fee1752cdc8f790a476efd2402b75181da88a9e61/librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c", size = 155152, upload-time = "2026-07-08T12:25:20.851Z" }, + { url = "https://files.pythonhosted.org/packages/0e/16/52b1c99bf19057a062aac39c900cbb81499f6f75d6c537c14463d247ba78/librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c", size = 502499, upload-time = "2026-07-08T12:25:22.055Z" }, + { url = "https://files.pythonhosted.org/packages/9f/54/b811151805c795f55e0dedee6ec687b75f9982a8105d240ea3910737a77b/librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b", size = 496108, upload-time = "2026-07-08T12:25:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/8f/f8/094d6b2bd93f3fdaa54db54cc788c4a365333bddad65ab02e04da0b1d004/librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9", size = 531576, upload-time = "2026-07-08T12:25:24.648Z" }, + { url = "https://files.pythonhosted.org/packages/2e/40/541733d5755824f968f7ec39d78ffbd75d145964157ae5e69a09ec6d7326/librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db", size = 524390, upload-time = "2026-07-08T12:25:25.898Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b5/255673cfdbf5ba663339d36cd863c897289ab4337577e19f9405ce059f36/librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6", size = 543053, upload-time = "2026-07-08T12:25:27.436Z" }, + { url = "https://files.pythonhosted.org/packages/9e/11/ab5005e9c9850710f21e354201bf090646349d3fabf5f951eaf70235729e/librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7", size = 546387, upload-time = "2026-07-08T12:25:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/a2/04/a5d7ce1d1df1afd15ca283dcdf7530ac073e12d69ae8c40879dda96f7868/librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1", size = 535970, upload-time = "2026-07-08T12:25:30.171Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/927e267a6daa290174ac281b23c9804c8829b042ade9c6f24a065f540958/librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a", size = 573582, upload-time = "2026-07-08T12:25:31.507Z" }, + { url = "https://files.pythonhosted.org/packages/10/24/b6c5213efe39c19f9e13605644d0cf063b4ddaa33ac2e45b088e23a70e2e/librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628", size = 82189, upload-time = "2026-07-08T12:25:32.675Z" }, + { url = "https://files.pythonhosted.org/packages/4c/00/d29736be177a906ac0b84a5b04b4fbfa22c776dc2f366de4172b0f968c08/librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927", size = 106193, upload-time = "2026-07-08T12:25:33.692Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ac/aff6fb45393cb8912f39dfb156ef6b2d1cadb207ff465fc8f66141054be8/librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650", size = 126962, upload-time = "2026-07-08T12:25:34.769Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3a/d68cb2b334d53fd30fac81d3a489ce4ba0d9506f4df43fcf676b68352b19/librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566", size = 112127, upload-time = "2026-07-08T12:25:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/7b/66/f49ae0d592bd45b6941e9a8bafcb6a87cddcd501ee7874707e767f01b585/librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71", size = 149818, upload-time = "2026-07-08T12:25:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/3d/50/51c76d74014d04fb95b6506d286808984b78a2f7a41039094e6b2194ac48/librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6", size = 154071, upload-time = "2026-07-08T12:25:39.399Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fe/f19b0f5f82d5a1f2da736586bc840abd00ce07d6388136ae80b7333883fc/librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f", size = 494168, upload-time = "2026-07-08T12:25:40.641Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/b8550c75775127fd31a5f20e8775997f7b527ad661fc8ddccd7497c064f7/librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180", size = 491054, upload-time = "2026-07-08T12:25:41.905Z" }, + { url = "https://files.pythonhosted.org/packages/30/14/4d0204867623df3f33f86efd3d3692ba5e01321443f4d6eab35a22697618/librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6", size = 523006, upload-time = "2026-07-08T12:25:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/19/0a/c45fc9a260934696bace1ac5df1e148ac92bd71767aee3bf7cd7a4534f4c/librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9", size = 515058, upload-time = "2026-07-08T12:25:44.541Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/50c5ce45b326854ef8fa6ae4c36cf5142e5c55315eaf9e51d0ae73ac4da3/librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007", size = 534025, upload-time = "2026-07-08T12:25:45.825Z" }, + { url = "https://files.pythonhosted.org/packages/89/2d/08c413c8f93fc13b8103624fce38e5caa86cd08cbbc8465870ab287af54b/librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0", size = 540557, upload-time = "2026-07-08T12:25:47.059Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/93af71fb4a364952210051811dd4e40174e79656b050c89cacac18af3330/librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1", size = 523201, upload-time = "2026-07-08T12:25:48.392Z" }, + { url = "https://files.pythonhosted.org/packages/c1/6e/9766f07b676a4889d9f8bc2864e9ba5fff165653143ef4dda7df6aa34d16/librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d", size = 565740, upload-time = "2026-07-08T12:25:49.678Z" }, + { url = "https://files.pythonhosted.org/packages/a2/1e/664e3472ce2b6e10e9b83f29d4a36eb982ff6b5a169ae7567bba3a4c4ff5/librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16", size = 81611, upload-time = "2026-07-08T12:25:50.857Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/8582a4d65e2234673685e07309d02c230b28a85724eb0acbf13f019b7f6e/librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37", size = 100106, upload-time = "2026-07-08T12:25:52.03Z" }, + { url = "https://files.pythonhosted.org/packages/63/ce/0cb99efe6086b46cd985dc26672166fae312a239690e75871f7fafbd3fc5/librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39", size = 121209, upload-time = "2026-07-08T12:25:53.166Z" }, + { url = "https://files.pythonhosted.org/packages/26/85/4f3ccb083a3c9b0d42e223acdb3c3f507953324a59cdcab4826e8e2e3b89/librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6", size = 106404, upload-time = "2026-07-08T12:25:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/b2/77/333191499538c8e8189de7a4cba8e6f49ee949fd6d6e6324b21fd1522466/librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5", size = 159231, upload-time = "2026-07-08T12:25:55.432Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9e/2aa83758f22c278b837a1d8025898434ce2b8bff36678d5330ecaef56dff/librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46", size = 161300, upload-time = "2026-07-08T12:25:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c0/86791e936553ca763d6b3c2fb4d31d596cd00e14fa631c283a40ba01559a/librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e", size = 582056, upload-time = "2026-07-08T12:25:58.144Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d3/a9ec15984a185e000c4d2a16ba28bd623124ad4c38a10974c7ff78e3a893/librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a", size = 562758, upload-time = "2026-07-08T12:25:59.544Z" }, + { url = "https://files.pythonhosted.org/packages/3c/af/dbe36b78b19c06a55097f99305e4ea9458e2273e6ae16a3cbecaad7ee978/librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22", size = 602095, upload-time = "2026-07-08T12:26:00.991Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a8/2966891b4dd2830f5203fbee92ac2c4947653a2390ba73dfa44244fad025/librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c", size = 593452, upload-time = "2026-07-08T12:26:02.352Z" }, + { url = "https://files.pythonhosted.org/packages/61/f5/4df8bfc8405ecf8c0d525b4d69636f694bdd8620b313ec8b76e54a5926cc/librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0", size = 623729, upload-time = "2026-07-08T12:26:04.294Z" }, + { url = "https://files.pythonhosted.org/packages/d6/13/9ac202dffc8db06f75d06c08c2f9f6ff054be67d21272dcc078fa1cc0c57/librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04", size = 617077, upload-time = "2026-07-08T12:26:05.845Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f0/ebe38610716aee5cb28efd95089bb90192096179802779381e1c5dcf239c/librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61", size = 599561, upload-time = "2026-07-08T12:26:07.21Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5c/c2e72e236fff7abc716d5b1753b8b8cd3ea85ac46fe17d2e7c51d4e1c723/librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9", size = 645511, upload-time = "2026-07-08T12:26:08.562Z" }, + { url = "https://files.pythonhosted.org/packages/0c/99/6203ce619dee940d6bfbe099ec3fe4be00a68e9d60f70abf906cf124fe66/librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18", size = 104357, upload-time = "2026-07-08T12:26:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/52/dd/843b6314087c41657c7036d7914d8f294bdf9b580aa8513ea0588c8e9a3d/librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259", size = 126998, upload-time = "2026-07-08T12:26:10.975Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/3dcec2884ba1b0806d1408612555c38dd5d68e90156b59f75f6e36435c3a/librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99", size = 110771, upload-time = "2026-07-08T12:26:12.303Z" }, +] + +[[package]] +name = "license-expression" +version = "30.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boolean-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/71/d89bb0e71b1415453980fd32315f2a037aad9f7f70f695c7cec7035feb13/license_expression-30.4.4.tar.gz", hash = "sha256:73448f0aacd8d0808895bdc4b2c8e01a8d67646e4188f887375398c761f340fd", size = 186402, upload-time = "2025-07-22T11:13:32.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/40/791891d4c0c4dab4c5e187c17261cedc26285fd41541577f900470a45a4d/license_expression-30.4.4-py3-none-any.whl", hash = "sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4", size = 120615, upload-time = "2025-07-22T11:13:31.217Z" }, +] + +[[package]] +name = "lxml" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/3b/aab6728cae887456f409b4d75e8a01856e4f04bd510de38052a47768b680/lxml-6.1.1.tar.gz", hash = "sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40", size = 4197430, upload-time = "2026-05-18T19:19:06.424Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/6e/c4add832b6fc1e887125b96f880d7b9b70aae5248718e046b1704bcac4b9/lxml-6.1.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:104c09bda8d2a562824c0e319d0768ce26a779b7601e0931d33b09b53c392ef7", size = 8570821, upload-time = "2026-05-18T19:17:42.068Z" }, + { url = "https://files.pythonhosted.org/packages/22/00/ff3009c88e65de8011630acf8ab5a09cb2becd2aaf47fba2f3449f6224e9/lxml-6.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:25c6997a9a534e016695a0ba06b2f07945de682731ff01065b6d5a4474179da1", size = 4624252, upload-time = "2026-05-18T19:17:47.897Z" }, + { url = "https://files.pythonhosted.org/packages/42/95/bb63f0fd62e554fe078e1fb3c8fe9083c14ddc7ad7fa178d10e57e071ac7/lxml-6.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c921ba5c51e4e9f63b8b00267d06566e1f63407408a0496da2d1d0bfc819c7fc", size = 4930746, upload-time = "2026-05-18T19:18:29.637Z" }, + { url = "https://files.pythonhosted.org/packages/eb/99/0013e8d9b5960f4f041cf0b73e2f80c23eb5205b1f7bfb20203243651359/lxml-6.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:54a7f95e4de5fb94e2f9f4b9055c6ba33bf3d628fd77a1d647c5923caa2cdcdc", size = 5093723, upload-time = "2026-05-18T19:18:34.168Z" }, + { url = "https://files.pythonhosted.org/packages/29/91/317b332636bfc7bddcff828d41b3307f50043f4b237e40849c333d80fa1a/lxml-6.1.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f2ec43df44b1f76249ee0a615334f9b5b060e1c8bd90e706dad2d14d02f383", size = 5005557, upload-time = "2026-05-18T19:18:39.798Z" }, + { url = "https://files.pythonhosted.org/packages/42/2f/cc9bf06afe70f9c9093ae60855d9759da9db601ec4080f7473319666ffd7/lxml-6.1.1-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:70ef8a7e102a1508f8121aae5b0867abd663f72c14f0a9c937e6554cb4587b7b", size = 5631036, upload-time = "2026-05-18T19:18:44.858Z" }, + { url = "https://files.pythonhosted.org/packages/08/f6/af32e23e563971ffb0fb86be52bc5be5c2c118858ffc119bf6a9039b173d/lxml-6.1.1-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebe6af670449830d6d9b752c256a983291c766a1365ba5d5460048f9e33a7818", size = 5240367, upload-time = "2026-05-18T19:18:49.217Z" }, + { url = "https://files.pythonhosted.org/packages/78/83/8555d40948b09ce86f1bd0c68a7ac31d07b1929f92cc1b074006c97ef2d2/lxml-6.1.1-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:27acc820660aaffa4f7c087f29120e12980f7779d56d8492d263170111284740", size = 5350171, upload-time = "2026-05-18T19:18:52.779Z" }, + { url = "https://files.pythonhosted.org/packages/63/75/5d92da93729b7bad783689e6496049fa40927b45bec7bf183c981de3ca70/lxml-6.1.1-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:1db753c9115ec7100d073b744d17e25e88a8f90f5c39b2f5dd878149af59671f", size = 4694874, upload-time = "2026-05-18T19:18:55.139Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b5/3aad415a9a25b822e783f15deeb4dffccf5113030f1afa2222dd929313d9/lxml-6.1.1-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4f469aebd783bb741c2ecb2a681008fd26bfe5c16a9a72ed5467f834e810df2", size = 5244492, upload-time = "2026-05-18T19:19:01.28Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a1/5fcf7eb9904b80086aa47dcf0027de07b1bb990afad2e6823144c368ae04/lxml-6.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:766b010012d59470072c1816b5b6c69f1d243e5db36ea5968e94accf430a4635", size = 5048232, upload-time = "2026-05-18T19:18:12.67Z" }, + { url = "https://files.pythonhosted.org/packages/77/74/1f601b63c7a69fcdf10fa9b148c81da8442204194f6c55509cc485c786b9/lxml-6.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b8d812c6011c08b8111a15e54dd990b8923692d80adf35488bee34026c35accf", size = 4777023, upload-time = "2026-05-18T19:18:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/a2/b9/7a78f51aec95b1bf780d78e12705a9f6533284f8693dc5c0e6724fa53d3f/lxml-6.1.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:fe0306bd29505a9177aac19f1877174b0e7422c222a59f70b2cd41633448c3dc", size = 5645773, upload-time = "2026-05-18T19:18:23.223Z" }, + { url = "https://files.pythonhosted.org/packages/a5/6e/98a7b7ad54e4e74fa1f20fff776913980619d0ebe5558232d7da6580bdd8/lxml-6.1.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5ba186ad207446c65d3bb3d3e0412b032b1d9f595e59861e2354798c5703d955", size = 5233088, upload-time = "2026-05-18T19:18:31.433Z" }, + { url = "https://files.pythonhosted.org/packages/65/d1/bc0ed2427bf609f2ee10da303a6a226f9c8bce94f945dc29a32ce55de6e4/lxml-6.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aa366a1e55b8ebfe8ca8ddc3cfe75c8ebade181aeb0f661d0cb05986b647f72a", size = 5260995, upload-time = "2026-05-18T19:18:37.091Z" }, + { url = "https://files.pythonhosted.org/packages/69/8b/6772e1a4b513fc50a8d931f19edde0e13ae6918510a1e13ff67864f3e5ed/lxml-6.1.1-cp312-cp312-win32.whl", hash = "sha256:126c93f7f56f0eda92f6d8c619edc463a4f23d9252f1c9d0405a76f25fa9f11a", size = 3596382, upload-time = "2026-05-18T19:17:18.37Z" }, + { url = "https://files.pythonhosted.org/packages/1b/89/45198e9624762af2dfd2cb8782598477ceb29f6e59caab560388ae1f4ec1/lxml-6.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:26e6eda8d38c1fcab1090dd196ee87cbd13788e531937610e2589085de074e77", size = 3997255, upload-time = "2026-05-18T19:17:56.781Z" }, + { url = "https://files.pythonhosted.org/packages/90/a9/7a54b6834088d9ae528a7b780584ba6a39a9457b0ac330479f20ffbc9449/lxml-6.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:6540377fbd53fe1b629172288c464fb18db11ce1fa7dc15891da10aa9dcc3e7f", size = 3659610, upload-time = "2026-05-19T19:22:50.843Z" }, + { url = "https://files.pythonhosted.org/packages/a5/eb/7e6f37c5584ccbb2ff267f56fd0339016938c1c8684cfefab9b33ffc2f36/lxml-6.1.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:68a9198d0fc122d14bb76837de9aa80cf84caed990b5b237f532ed87d3706736", size = 8559780, upload-time = "2026-05-18T19:17:57.661Z" }, + { url = "https://files.pythonhosted.org/packages/a1/36/587c2521cf23a2cd6c9c22108aa7528f683a1f195ed7ccd23a4b1786ad36/lxml-6.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7d47866cb32fb503450b6edc9df355d10dc49836af2e89901bd6ac6b0896d9d9", size = 4618006, upload-time = "2026-05-18T19:18:04.452Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ca/ab7bfe2bf4c972af5e7878262845ead3a24a929a9b04bc11c7c1ece6c82a/lxml-6.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb7c9811bfaa8b1ed5ed319f5d370dfbcaa59d52ea64be2a5a85e18195930354", size = 4924139, upload-time = "2026-05-18T19:19:04.873Z" }, + { url = "https://files.pythonhosted.org/packages/6b/55/a0c72851dfee5ecc689f949723a73dea457758912542cb955b108eaf0d8f/lxml-6.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:762ff394d5bd56da0cf034a23dcce4e13923f15321a2adfa2ac00201dc6d3fca", size = 5082329, upload-time = "2026-05-18T19:19:09.728Z" }, + { url = "https://files.pythonhosted.org/packages/f0/b6/0608f7d61a3b96cc67e5648a3d906e31a5082093e10e7be65b3886289938/lxml-6.1.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a088f287f7d8275a33c07f2cac6c50b9319309a0200a39e7e75d80c707723099", size = 4993564, upload-time = "2026-05-18T19:19:13.608Z" }, + { url = "https://files.pythonhosted.org/packages/4c/66/ae227524b066d29d55bf0b453d93d2d793c40218657d643dcbbca13b8faf/lxml-6.1.1-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e902da4b04e6b52e5893900d4b8ab46068f75f3561f01bf1080957f9fd932ed6", size = 5613467, upload-time = "2026-05-18T19:19:16.228Z" }, + { url = "https://files.pythonhosted.org/packages/a6/76/dbe4a00b50385e40194231dcfe5a12c059de7cf90e89c83407d2b085b719/lxml-6.1.1-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d4962d4c66bf830a7e59ed6cfc17d148149898a3aefa8ec6e59763e6e3ed085", size = 5228304, upload-time = "2026-05-18T19:19:19.354Z" }, + { url = "https://files.pythonhosted.org/packages/1c/01/00b1b8442ed2041793336868ba0b9ea4b13d7da7c085c6404c207a63bf79/lxml-6.1.1-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:581d4c8ae690a6609e64862dd6b7c2489635c2d13907fc2b20f2bc200ff1d21e", size = 5341607, upload-time = "2026-05-18T19:19:22.297Z" }, + { url = "https://files.pythonhosted.org/packages/63/36/1ad29931e9a4638bb707869f01d423a6c815f82152138d1a40dfcfde2b95/lxml-6.1.1-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:876e1ff5930ed8bf295ec5ef9a8155e9b6b1876bbf1deed8b3a8069311875a8f", size = 4700168, upload-time = "2026-05-18T19:19:25.133Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d1/a9536cecf9be18a0dc72d32bead283a2332d1ffebd2dd3ac70ce444686e5/lxml-6.1.1-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9eb9b5a968f6e0f6d640092a567e14529ff8cea2e29d00da6f78a79fa49f013c", size = 5232487, upload-time = "2026-05-18T19:19:28.603Z" }, + { url = "https://files.pythonhosted.org/packages/0e/77/b4fb1e03bf5d130e879214d3100092e386418807fb74dd0adc4b0a48f351/lxml-6.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:aa49e06d94aba782c6a02eecb7e507969e7e7a41b267f1b359bb35585f295d5b", size = 5044231, upload-time = "2026-05-18T19:18:42.246Z" }, + { url = "https://files.pythonhosted.org/packages/26/4c/d00daeeb0a5530c4028a9232aa1b93db3ef4ed2158c116ea73c79a9765b3/lxml-6.1.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:70cdfd80589d59e43e18005dd7244e8895e93db8ab6a620b7e23df5445a4e3d2", size = 4769450, upload-time = "2026-05-18T19:18:48.013Z" }, + { url = "https://files.pythonhosted.org/packages/ed/6a/715a3a8d156ce42f29cf014706f5410c2ff3b02267774110fc23266409fe/lxml-6.1.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:aad9aa39483ed8ec44d6d2e59e5b98a0d80676ef0d92f44bfc374836111f62f5", size = 5635874, upload-time = "2026-05-18T19:18:51.914Z" }, + { url = "https://files.pythonhosted.org/packages/45/37/0544bc21dde2a88f3a17b504e6fc79c0e01d25a33c2f6079724e9e72b9c7/lxml-6.1.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d49514be2f28d895c38cf9d2b72d7b9a07d00314519f456c0b50b53cfcf4c785", size = 5223987, upload-time = "2026-05-18T19:18:59.715Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f8/f6a5e8185bcb28c2befae3d31f8e3df3b811cb0f47746517a81279fcafe1/lxml-6.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:47402e62c52ff5988c1e8c6c63177f5708bccf48e366dea4e3dcf1e645e04947", size = 5250276, upload-time = "2026-05-18T19:19:03.834Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f2/1a2b9f1b7a49d45495369be7ef9ad05b262930f2eab3e3145706fca8083f/lxml-6.1.1-cp313-cp313-win32.whl", hash = "sha256:3483644525531e1d5762b0c44a8e18b6efba321b6dcf8a8952de10b037618bca", size = 3596903, upload-time = "2026-05-18T19:17:29.863Z" }, + { url = "https://files.pythonhosted.org/packages/e6/99/f4ffb024f238eec2131aaa09f3278fb6129cf892741bf68e1fc1afb8c100/lxml-6.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:a10bd2fd62e8ce916ececb342f348f190724a098c1faa056fdfb2a22ad5e8660", size = 3995869, upload-time = "2026-05-18T19:18:02.596Z" }, + { url = "https://files.pythonhosted.org/packages/d1/53/70eb8c5c6037f27448f1e3c54ebede9545a801ae63f0a7254afca4fe8e45/lxml-6.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc", size = 3658490, upload-time = "2026-05-19T19:22:53.846Z" }, + { url = "https://files.pythonhosted.org/packages/13/e2/2e325795566de01d0d7c3bb57d3c370616b2d07b01214e84eec5d3b10963/lxml-6.1.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:19b7ab10b210b0b3ad7985d9ac4eb66ab09a90b20fe6e2f7ba55d01a234345d0", size = 8577146, upload-time = "2026-05-18T19:18:17.765Z" }, + { url = "https://files.pythonhosted.org/packages/93/cf/5630b5e4be7d2e6bee8efe83865c925221103cf0221303b104ce134b01e2/lxml-6.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c08e5c694306507275f2290073350c4f32e383db15213b2c69e7ff39c1193840", size = 4623866, upload-time = "2026-05-18T19:18:30.669Z" }, + { url = "https://files.pythonhosted.org/packages/d2/51/3904907c063451cf8d4a5c9fe0cad95fa1f4ec57f4e3884fa0731bd7a305/lxml-6.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:74a9717fd0d82effef5c2854f0d917231d5324b5a3eb7275c43ac9fa32f97a14", size = 4950022, upload-time = "2026-05-18T19:19:31.958Z" }, + { url = "https://files.pythonhosted.org/packages/94/cd/9c7611a51c37a2830928405817cc5d56a97f64fab83cc3f628748b135749/lxml-6.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efe0374196335f93b53269acd811b944f2e6bdc88e8894f214bd636455484909", size = 5086695, upload-time = "2026-05-18T19:19:34.764Z" }, + { url = "https://files.pythonhosted.org/packages/da/d6/24e3b5906abb0b674ff2ae195bc3ce59708df2bcd17cf17703b2d7dd643a/lxml-6.1.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac931cdc9442c1763b8a8f6cd62c0c938737eafc5be75eff88df55fc73bc0d00", size = 5031642, upload-time = "2026-05-18T19:19:37.771Z" }, + { url = "https://files.pythonhosted.org/packages/2d/db/6ec54f99019838bff54785c51da07f189eb4676861c5f2730962b0d8d665/lxml-6.1.1-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:aee395f5d0927f947758b4ec119fd5fc8ec71f07a1c5c52077b30b04c0fa6955", size = 5647338, upload-time = "2026-05-18T19:19:40.553Z" }, + { url = "https://files.pythonhosted.org/packages/42/3d/ef4dcfffd22d27a61805d8ed9f7fb888495bc6aa88648fa07c1eaa5586b6/lxml-6.1.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9395002973c827b3ed67db77e6ec09f092919a587022174554096a269378fb13", size = 5239528, upload-time = "2026-05-18T19:19:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/62/bb/37fb3f0dff146bdcfa78eec47879273820b2a0bf350ec236ce14bd0b1c26/lxml-6.1.1-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:73bc2086f141224ebddb7fc5c6a36ca58b31b94b561e1dfe8e073e3270fad1e7", size = 5350730, upload-time = "2026-05-18T19:19:46.307Z" }, + { url = "https://files.pythonhosted.org/packages/90/42/43253f168388df4fae1f38c01df36ddb9bee39e2048167b54cdcbae85ea3/lxml-6.1.1-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:3779def59032b81e44a5f70096ef6bf2082f8d901937dca354474ba09782e245", size = 4697530, upload-time = "2026-05-18T19:19:49.889Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a8/c5a8504f81bbdfc8e7094c2c850cdb4ed6777fc4d5ddd9e5ab819f3b0d54/lxml-6.1.1-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:86c89b9d55ebf820ad7c90bc533410f0d098054f293351f10603c0c46ff598f5", size = 5250670, upload-time = "2026-05-18T19:19:53.199Z" }, + { url = "https://files.pythonhosted.org/packages/77/b7/c7e76ab18744d75e21f320ebf9ff9d1ceae2b54dd431ea5a64caf26c9672/lxml-6.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19607c6bbff2a44cf3fe8250abccd20942d3462473e0a721d01d379ed017e462", size = 5084485, upload-time = "2026-05-18T19:19:08.422Z" }, + { url = "https://files.pythonhosted.org/packages/31/31/b35c53f8ef7b7c31cacd23d3638652fff7bcd1deb6eedb709ab43b685908/lxml-6.1.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c6ed5141a5c7507cf3ee76bd363b0d6f801e3321adc35b5d825a23115faa5465", size = 4737635, upload-time = "2026-05-18T19:19:12.321Z" }, + { url = "https://files.pythonhosted.org/packages/d9/06/31f23c813a7fe8e0cb1b175e915b08c9bf4e86d225b210feadbdbe519667/lxml-6.1.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:62aeb7e85b5d60320b9d77eef2e773994e2c0ce10121b277e0a19804e1654a5a", size = 5670681, upload-time = "2026-05-18T19:19:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bc/ce619bccc89b1fd9ad8a8e1330ee3f3beff9f2ff95b712d7bbcdd6e22fc3/lxml-6.1.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b1b963fd8f5caa68e99dfae060d54de1fe9cba899b8718b44a00cdca53c3e590", size = 5238229, upload-time = "2026-05-18T19:19:18.131Z" }, + { url = "https://files.pythonhosted.org/packages/2f/5d/b329acbbedc0b619ebc2be6cf7ee9ed07e80892c88d4dfd612c33805789a/lxml-6.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63876be28efefa04a1df615b46770e82042cce445cfdce55160522f57b231ccb", size = 5264191, upload-time = "2026-05-18T19:19:21.118Z" }, + { url = "https://files.pythonhosted.org/packages/d6/85/be36fb1425b30db3c3f9df75fe86343ebffb79e6320bd7f588e25bfeac39/lxml-6.1.1-cp314-cp314-win32.whl", hash = "sha256:7f7a92e8583f06b1fd49d01158143b8461cfcd135dcb10ec807270a3051bd603", size = 3657202, upload-time = "2026-05-18T19:17:39.509Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ce/3cf9a827342269f54d405a6202397de63f07c69cbd6ce7d183a3f0cba1e9/lxml-6.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:b2d444f2e66624d68e9c6b211e28a76e22fff5fcabcfff4deac18b529b7d4137", size = 4064497, upload-time = "2026-05-18T19:18:14.662Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3e/1a957bde8f0760039e627f94699f82caa782c9d838d86c3d28245ee67212/lxml-6.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:3fd9728a2735fda14f4e8235830c86b539e9661e849665bf926d3f867943b4bf", size = 3741991, upload-time = "2026-05-19T19:22:59.111Z" }, + { url = "https://files.pythonhosted.org/packages/78/b2/00ed55b3a2efa4658fb795c38d1090ec9b3e8a6c3683d4441fa517f09c3b/lxml-6.1.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:787b2496d0dbe8cd180984e8d29e3a6f76e7ea34db781cb3bd55e4ba1ef8b4ee", size = 8827545, upload-time = "2026-05-18T19:18:41.193Z" }, + { url = "https://files.pythonhosted.org/packages/c0/73/74573db19baa618d5f266f2407898b087ff6927115b00b71e5fc1b700847/lxml-6.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2c8daa471358dc2d6fcf02165e80ec68f77871a286df95bc5cc3816153b0fd2c", size = 4735736, upload-time = "2026-05-18T19:18:46.761Z" }, + { url = "https://files.pythonhosted.org/packages/16/02/6f7061f4f95f51e545d48e87647c54791d204a4e881be4156e7a26ba5338/lxml-6.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:acd7d70b64c0aae0c7922cca83d288a16f5f6da523637697872253415269baef", size = 4970291, upload-time = "2026-05-18T19:19:56.215Z" }, + { url = "https://files.pythonhosted.org/packages/b0/02/55fc057d8283427dea7d6edb102e7a840239c77a64a983d92f62a304c0e9/lxml-6.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4f0dd2f01f9f8a89f565d000e03abcf0a13d692a346c8d22f628d49af098777a", size = 5102822, upload-time = "2026-05-18T19:19:59.223Z" }, + { url = "https://files.pythonhosted.org/packages/e4/48/8e1cf78d89d66850121d9255a2a24414c98f775da93b90cf976956c24b14/lxml-6.1.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b7e8a14c8634bf6f7a568634cb395305a6d964aeb5b7ee32248094bed3a7e2c", size = 5027923, upload-time = "2026-05-18T19:20:01.549Z" }, + { url = "https://files.pythonhosted.org/packages/ed/00/0632a0647612c8af24d26997b3b961397daa9d5b2581444805933629a4cb/lxml-6.1.1-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:86281fbdd6a8162756f8d603f37e3435bfa38043adb79c6dc6a2dfee065e7525", size = 5595843, upload-time = "2026-05-18T19:20:03.93Z" }, + { url = "https://files.pythonhosted.org/packages/bc/86/ab008a7dc360711b66858d61c80a5979a70a09f2aa2b05d9698df80b803d/lxml-6.1.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5d7152ec39ca7c402d8fb9bad86140a15b9503bd0c54484e3f1bbe3dd37ceca", size = 5224515, upload-time = "2026-05-18T19:20:06.381Z" }, + { url = "https://files.pythonhosted.org/packages/75/c6/2702ff375e728e34f56d9a45339a9cf7e4427e917f542225242d63a05afa/lxml-6.1.1-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:88d8cb75b9d82858497a5393e3c63cfbf03035225e4b35a49ed7ccb151e4dc0e", size = 5312511, upload-time = "2026-05-18T19:20:09.308Z" }, + { url = "https://files.pythonhosted.org/packages/b7/57/a5807c98f87a86f10ef9ffab35516df7c0f0c4b6d5d33e9f608ab9c04a31/lxml-6.1.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f64ec5397ea6a41fc1b4af0380d79b44a755b5531dcaccd9940fb260dca93038", size = 4639206, upload-time = "2026-05-18T19:20:11.704Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e1/8a0a2c35734812395f4da4eaf33748a7e5705bfb2a58b128da764339d5ec/lxml-6.1.1-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d34bbf07dbc7ca5970671b1512e928991fb5e9d95365636c9b2d8b4f53af405e", size = 5232404, upload-time = "2026-05-18T19:20:14.064Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e2/0e6a4dd5ad84d01d99aa7bae7cfefd4a760a0e0f8176818241de17d9b6c0/lxml-6.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:17e0e18d4ad8adbd0399291bc44845b69d9dd68439a3cdebdf35ff902ec05072", size = 5083769, upload-time = "2026-05-18T19:19:23.758Z" }, + { url = "https://files.pythonhosted.org/packages/a0/7e/161f33d463f6ffc1c7679104b65086dea120080d49dde4d238f015aaee2f/lxml-6.1.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:3ab541146f1f6968c462d6c2ac495148e8cdba2f8347700b2141b6ec5a75bf52", size = 4758936, upload-time = "2026-05-18T19:19:27.256Z" }, + { url = "https://files.pythonhosted.org/packages/f1/fb/2369825e3f6ca99305bf9f7b7085fda91c8b0922a89e54d900974aa3ef85/lxml-6.1.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2a0217714657e023ef4293500f65aa20fce6164c8fd6b08fa5bd4a859fb14b9b", size = 5620296, upload-time = "2026-05-18T19:19:29.993Z" }, + { url = "https://files.pythonhosted.org/packages/30/90/d61e383146f74c5ab683947ea14dc7b82778838ab9b95ea73a23b60d0191/lxml-6.1.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:05a82eb6e1530a64f26225b55cbd178113bd0b5af1c2b625f25e5296742c26d2", size = 5228598, upload-time = "2026-05-18T19:19:33.523Z" }, + { url = "https://files.pythonhosted.org/packages/76/2d/2dafd8149e94b05bb070690efd5bb2680720681e03ff03fc57d2b70a1105/lxml-6.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9e36f163528fc50cbef305f02a5fd66d404edf7049cdaff211dbc2cba5a7013e", size = 5247845, upload-time = "2026-05-18T19:19:36.649Z" }, + { url = "https://files.pythonhosted.org/packages/ce/68/b30e913340c380ddac9580c6e6230991fc37240ec4f64704833e4f3e2769/lxml-6.1.1-cp314-cp314t-win32.whl", hash = "sha256:649dda677cf3bd6ac9ae14007ba0c824ded8ce5808b53fc7431d9140399118c1", size = 3897345, upload-time = "2026-05-18T19:17:33.562Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4e/9eb2af5335545f9fbcd7af57bcf87c6025d31eaa31b14ec184a6c8675328/lxml-6.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:793033d6c5cdf33a573f910d9bea14ef8f5771820411d118da8e1182edb53d5e", size = 4393350, upload-time = "2026-05-18T19:18:10.076Z" }, + { url = "https://files.pythonhosted.org/packages/7f/2c/0f1e93c636720e8a3eb59af2bfda99d98b55891e1c53bc30c2e0e865f01b/lxml-6.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:58bb955caba94e467d2a96da17660d2d704e0675894cba21ab8a775b8621fd1c", size = 3817223, upload-time = "2026-05-19T19:22:56.823Z" }, +] + +[[package]] +name = "lxml-stubs" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/da/1a3a3e5d159b249fc2970d73437496b908de8e4716a089c69591b4ffa6fd/lxml-stubs-0.5.1.tar.gz", hash = "sha256:e0ec2aa1ce92d91278b719091ce4515c12adc1d564359dfaf81efa7d4feab79d", size = 14778, upload-time = "2024-01-10T09:37:46.521Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/c9/e0f8e4e6e8a69e5959b06499582dca6349db6769cc7fdfb8a02a7c75a9ae/lxml_stubs-0.5.1-py3-none-any.whl", hash = "sha256:1f689e5dbc4b9247cb09ae820c7d34daeb1fdbd1db06123814b856dae7787272", size = 13584, upload-time = "2024-01-10T09:37:44.931Z" }, +] + +[[package]] +name = "mako" +version = "1.3.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/62/791b31e69ae182791ec67f04850f2f062716bbd205483d63a215f3e062d3/mako-1.3.12.tar.gz", hash = "sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a", size = 400219, upload-time = "2026-04-28T19:01:08.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/b1/a0ec7a5a9db730a08daef1fdfb8090435b82465abbf758a596f0ea88727e/mako-1.3.12-py3-none-any.whl", hash = "sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9", size = 78521, upload-time = "2026-04-28T19:01:10.393Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "msgpack" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8377a5ad8953fc0437c70cc98d9ae29f27fe5ac5109fbec0812085865735/msgpack-1.2.1-cp312-cp312-win32.whl", hash = "sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac", size = 64504, upload-time = "2026-06-18T16:13:08.822Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/ce1e377df7e62461fefd9eb23bfb93a4a523f40a517b377b8f844d836828/msgpack-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24", size = 71421, upload-time = "2026-06-18T16:13:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/8f/32/ebfe84c9929f08f188d56c7a2fd913406a9ddad76a634697c1c43b8112e6/msgpack-1.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07", size = 64775, upload-time = "2026-06-18T16:13:11.056Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ac/dcddcab6f6c20ecb387ca5e980371cdb3f87ff69aeca388be97eebc4c074/msgpack-1.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064", size = 83151, upload-time = "2026-06-18T16:13:12.173Z" }, + { url = "https://files.pythonhosted.org/packages/64/71/fbcfa83a1d6a9c6091942d1cfd070962244664b87427a9a49a6897b1b219/msgpack-1.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056", size = 82351, upload-time = "2026-06-18T16:13:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/e3/10/ddf7b06db879e8792d13934ddda09ff20bd2a583fd84c9b59aae9b0e650b/msgpack-1.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc", size = 407518, upload-time = "2026-06-18T16:13:14.233Z" }, + { url = "https://files.pythonhosted.org/packages/79/d3/36a46a8ed992b781acbc05928bd5bee3c810cb0c3563bf81a7b0c04a1a76/msgpack-1.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d", size = 416405, upload-time = "2026-06-18T16:13:15.435Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/e8e9598b557c0ba6ddae901a73780a4c75ac667dddf59414b1e56a42fb34/msgpack-1.2.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155", size = 376257, upload-time = "2026-06-18T16:13:17.022Z" }, + { url = "https://files.pythonhosted.org/packages/40/16/738fe6d875ad7e2a9429c165322a4ec088f4f273cdfae63d96a89c467961/msgpack-1.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402", size = 397469, upload-time = "2026-06-18T16:13:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/ca/be/6d5952df75a7f24f35833af764c3a6860780364cb3a0030beb8099e1b2b4/msgpack-1.2.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c", size = 372802, upload-time = "2026-06-18T16:13:19.685Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/e2ef7dbf0473bcb8dc7c50bf782a892d67414877b63e47fc88eb189ef5e6/msgpack-1.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6", size = 411273, upload-time = "2026-06-18T16:13:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c5/133f4512a56e983a93445c836c9d94d88f3bc2e0980ff4b9e577bd8416ce/msgpack-1.2.1-cp313-cp313-win32.whl", hash = "sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707", size = 64471, upload-time = "2026-06-18T16:13:22.293Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/577e10b055096a7dd40732358cabaf7180a20c79ed1dcdbb618e4b9deac7/msgpack-1.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9", size = 71274, upload-time = "2026-06-18T16:13:23.455Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/0c0048e7cfbef23c6a94791b8959ab28155232e7956de8a305b5ff588f05/msgpack-1.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a", size = 64795, upload-time = "2026-06-18T16:13:24.687Z" }, + { url = "https://files.pythonhosted.org/packages/77/58/cce442852c6b9e1639c7c8ac8fd9143121cb32dab0f308df4d1426a8eb9c/msgpack-1.2.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:05f340e47e7e47d2da8db9b53e1bb1d294369e9ef45a747441309f6650b8351d", size = 83610, upload-time = "2026-06-18T16:13:25.724Z" }, + { url = "https://files.pythonhosted.org/packages/60/5c/15b4c7a0182f75ffa90751958ba36a9c01cafee367d49a3edc10ed140b01/msgpack-1.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:810b916696c86ef0deb3b74588480224df4c1b071136c34183e4a2a4284d7ac7", size = 83138, upload-time = "2026-06-18T16:13:26.781Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/99e58722feaffc5f2fbcc0c8c0d1451ab9f84097f7af87291b46af2390f4/msgpack-1.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ca0dacff965c47afdc3749a8469d7302a8f801d6a28758d55120d75e66ce6889", size = 406090, upload-time = "2026-06-18T16:13:28.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/03/8c63e8cf52958534ef688625965ab04c269a6cadd8caef16758b380a821a/msgpack-1.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e2bf9280bceb5efca998435904b5d3e9fdbcc11d90dc9df30aec7973252b720", size = 412106, upload-time = "2026-06-18T16:13:29.427Z" }, + { url = "https://files.pythonhosted.org/packages/63/d2/155d9e71b40e41fd934bc0c48b9b2770f22263e1ac20aad8e29fdca7be3f/msgpack-1.2.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6c4be5d1c02a42b066ca6ddb71adf36432868fdcdb6ee87e634e86e0674190", size = 374851, upload-time = "2026-06-18T16:13:30.631Z" }, + { url = "https://files.pythonhosted.org/packages/98/48/deaf2326262a8d5ea3295ce9649912ecd3f551ba7ec8e33c665d2ba583f3/msgpack-1.2.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec0e675d59150a6269ddc9139087c722292664a37d071a849c05c473350f1f2d", size = 396168, upload-time = "2026-06-18T16:13:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/2a/b4410f906c2ec0008f1608d3ab5143afc3ad3f4e6da0fed3ea2231d0bef4/msgpack-1.2.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:dd3bfe82d53edfe4b7fc9a7ec9761e23a7a5b1dac22264505af428253c29ed24", size = 371959, upload-time = "2026-06-18T16:13:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/86/1edc67270099a528fa2093ea60fe191233cd238e4bd30cfacf7db79fc959/msgpack-1.2.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5ad5467fc3f68b5468e06c5f788d712e9f8ffc8b0cd1bcb160c105c1ee92dae7", size = 408457, upload-time = "2026-06-18T16:13:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/82/90/8b630fef07d8c5ab457b71ff2c217910c83d333c7a68472c186e87cc504a/msgpack-1.2.1-cp314-cp314-win32.whl", hash = "sha256:98b58bdb89c46190e4609bb36abe17c6d4105ad13f9c5f8f6f64d320f8ced3fb", size = 65942, upload-time = "2026-06-18T16:13:36.056Z" }, + { url = "https://files.pythonhosted.org/packages/16/f1/467b81e98b24dd3885d7b1857728797b4ffc76a7a7483af4fb321a07de3c/msgpack-1.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:74847557e28ce71bd3c438a447ca90e4b507e997ddbdef8a12a7b283b86c156b", size = 72627, upload-time = "2026-06-18T16:13:37.079Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1d/5d8c4c89985feb6acefb82a09e501c60392261856d2408d20bfe4f0360b1/msgpack-1.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:b50b727bd652bdc37d950336c848ef20ec54a4cafc38dce19b1cd86ad625d0f7", size = 66908, upload-time = "2026-06-18T16:13:38.23Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ad2afb678b4de94496cd432b581759b756a92c1192d8c767edd6b132efdc/msgpack-1.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8d00f177ca88a77c1cf848d204a38f249751650b601cb6532acc68805d8a8273", size = 86000, upload-time = "2026-06-18T16:13:39.44Z" }, + { url = "https://files.pythonhosted.org/packages/54/74/0b797484013128837f3b1cbb6cea019277c4de4e377dc512b4d9a0f92940/msgpack-1.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5bb9c386f0a329c035ddbab4b72d1028bf9627add8dda41070288563d57ed1b1", size = 86544, upload-time = "2026-06-18T16:13:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b4/b774d7eb95561739907fec675582f83203cf41c597a418c2589b4bfb8e9d/msgpack-1.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20466cca18c49c7292a8984bc15d65857b171e7264bdcb5f96baf8be238791fc", size = 427661, upload-time = "2026-06-18T16:13:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f9/3243191dc9937e00756c8bc1b0272fed8f23758e43df2a3b46f533e5090f/msgpack-1.2.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:196300e7e5d6e74d50f1607ab9c06c4a1484c383cd22defd727902591f7e8dde", size = 426375, upload-time = "2026-06-18T16:13:42.936Z" }, + { url = "https://files.pythonhosted.org/packages/23/c7/1693111db9944ba4ad4b67a1e788400d78a0b6af7a6523dc7e4e58f8274b/msgpack-1.2.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575957e79cd51903a4e8495a242442949641e08f1efd5197b43bebd3ea7682b4", size = 380495, upload-time = "2026-06-18T16:13:44.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2b/92f86956a0c13e8662f7e2ad630c4eb4db07497b967589bd5245e018b2c1/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8c2ed1e48cc0f460bf3c7780e7137ff21a4e18433451916f2442c1b21036cd7d", size = 410897, upload-time = "2026-06-18T16:13:45.629Z" }, + { url = "https://files.pythonhosted.org/packages/da/ea/1479f72d200313a76fc2f823a79d1e07ed052ab7b8a0280640aa7b95de42/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5f6277e5f783c36786a145e0247fc189a03f35f84b251646e53592d2bc12b355", size = 378519, upload-time = "2026-06-18T16:13:46.998Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/fa006060ffa1011d32bfae826fe766fe73e02982183601633b7121058ab3/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9389552ecf4784886345ead0647e4edc96bee37cbab05b75540f542f766c48c", size = 419815, upload-time = "2026-06-18T16:13:48.205Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/aab6c946570496b78e67804721f3d5e2d62a93081b9b37df77764ef56347/msgpack-1.2.1-cp314-cp314t-win32.whl", hash = "sha256:c1c79a604a2969a868a78b6ebd27a887e00c624f14f66b3038e0590cb23332d1", size = 70914, upload-time = "2026-06-18T16:13:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/e608956488a2af014cfe6e3d665e090b8ee42aa14b07f8f95b8880d66b09/msgpack-1.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f12038a35fabd52e56a3547bab42401af49a45caa6dd00b34c44de235bc93ee2", size = 77999, upload-time = "2026-06-18T16:13:50.467Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8a/27e2e57055176e366a46b85d02d68e7a5bcfbdd8474c9706375d965f24d3/msgpack-1.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0adcf06ffde0777c0e1a9b771a2b1c4226ba1bbf748c8efcc02fcdeca3299107", size = 71160, upload-time = "2026-06-18T16:13:51.498Z" }, +] + +[[package]] +name = "mypy" +version = "1.20.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/af/e3d4b3e9ec91a0ff9aabfdb38692952acf49bbb899c2e4c29acb3a6da3ae/mypy-1.20.2.tar.gz", hash = "sha256:e8222c26daaafd9e8626dec58ae36029f82585890589576f769a650dd20fd665", size = 3817349, upload-time = "2026-04-21T17:12:28.473Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/4e/7560e4528db9e9b147e4c0f22660466bf30a0a1fe3d63d1b9d3b0fd354ee/mypy-1.20.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4dbfcf869f6b0517f70cf0030ba6ea1d6645e132337a7d5204a18d8d5636c02b", size = 14539393, upload-time = "2026-04-21T17:07:12.52Z" }, + { url = "https://files.pythonhosted.org/packages/32/d9/34a5efed8124f5a9234f55ac6a4ced4201e2c5b81e1109c49ad23190ec8c/mypy-1.20.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b6481b228d072315b053210b01ac320e1be243dc17f9e5887ef167f23f5fae4", size = 13361642, upload-time = "2026-04-21T17:06:53.742Z" }, + { url = "https://files.pythonhosted.org/packages/d1/14/eb377acf78c03c92d566a1510cda8137348215b5335085ef662ab82ecd3a/mypy-1.20.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34397cdced6b90b836e38182076049fdb41424322e0b0728c946b0939ebdf9f6", size = 13740347, upload-time = "2026-04-21T17:12:04.73Z" }, + { url = "https://files.pythonhosted.org/packages/b9/94/7e4634a32b641aa1c112422eed1bbece61ee16205f674190e8b536f884de/mypy-1.20.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5da6976f20cae27059ea8d0c86e7cef3de720e04c4bb9ee18e3690fdb792066", size = 14734042, upload-time = "2026-04-21T17:07:43.16Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f3/f7e62395cb7f434541b4491a01149a4439e28ace4c0c632bbf5431e92d1f/mypy-1.20.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:56908d7e08318d39f85b1f0c6cfd47b0cac1a130da677630dac0de3e0623e102", size = 14964958, upload-time = "2026-04-21T17:11:00.665Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0d/47e3c3a0ec2a876e35aeac365df3cac7776c36bbd4ed18cc521e1b9d255b/mypy-1.20.2-cp312-cp312-win_amd64.whl", hash = "sha256:d52ad8d78522da1d308789df651ee5379088e77c76cb1994858d40a426b343b9", size = 10911340, upload-time = "2026-04-21T17:10:49.179Z" }, + { url = "https://files.pythonhosted.org/packages/d6/b2/6c852d72e0ea8b01f49da817fb52539993cde327e7d010e0103dc12d0dac/mypy-1.20.2-cp312-cp312-win_arm64.whl", hash = "sha256:785b08db19c9f214dc37d65f7c165d19a30fcecb48abfa30f31b01b5acaabb58", size = 9833947, upload-time = "2026-04-21T17:09:05.267Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c4/b93812d3a192c9bcf5df405bd2f30277cd0e48106a14d1023c7f6ed6e39b/mypy-1.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:edfbfca868cdd6bd8d974a60f8a3682f5565d3f5c99b327640cedd24c4264026", size = 14524670, upload-time = "2026-04-21T17:10:30.737Z" }, + { url = "https://files.pythonhosted.org/packages/f3/47/42c122501bff18eaf1e8f457f5c017933452d8acdc52918a9f59f6812955/mypy-1.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e2877a02380adfcdbc69071a0f74d6e9dbbf593c0dc9d174e1f223ffd5281943", size = 13336218, upload-time = "2026-04-21T17:08:44.069Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/75bbc92f41725fbd585fb17b440b1119b576105df1013622983e18640a93/mypy-1.20.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7488448de6007cd5177c6cea0517ac33b4c0f5ee9b5e9f2be51ce75511a85517", size = 13724906, upload-time = "2026-04-21T17:08:01.02Z" }, + { url = "https://files.pythonhosted.org/packages/a1/32/4c49da27a606167391ff0c39aa955707a00edc500572e562f7c36c08a71f/mypy-1.20.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb9c2fa06887e21d6a3a868762acb82aec34e2c6fd0174064f27c93ede68ad15", size = 14726046, upload-time = "2026-04-21T17:11:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/7f/fc/4e354a1bd70216359deb0c9c54847ee6b32ef78dfb09f5131ff99b494078/mypy-1.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d56a78b646f2e3daa865bc70cd5ec5a46c50045801ca8ff17a0c43abc97e3ee", size = 14955587, upload-time = "2026-04-21T17:12:16.033Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/c0f2056e9eb8f08c62cafd9715e4584b89132bdc832fcf85d27d07b5f3e5/mypy-1.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:2a4102b03bb7481d9a91a6da8d174740c9c8c4401024684b9ca3b7cc5e49852f", size = 10922681, upload-time = "2026-04-21T17:06:35.842Z" }, + { url = "https://files.pythonhosted.org/packages/e5/14/065e333721f05de8ef683d0aa804c23026bcc287446b61cac657b902ccac/mypy-1.20.2-cp313-cp313-win_arm64.whl", hash = "sha256:a95a9248b0c6fd933a442c03c3b113c3b61320086b88e2c444676d3fd1ca3330", size = 9830560, upload-time = "2026-04-21T17:07:51.023Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d1/b4ec96b0ecc620a4443570c6e95c867903428cfcde4206518eafdd5880c3/mypy-1.20.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:419413398fe250aae057fd2fe50166b61077083c9b82754c341cf4fd73038f30", size = 14524561, upload-time = "2026-04-21T17:06:27.325Z" }, + { url = "https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924", size = 13363883, upload-time = "2026-04-21T17:11:11.239Z" }, + { url = "https://files.pythonhosted.org/packages/2a/56/983916806bf4eddeaaa2c9230903c3669c6718552a921154e1c5182c701f/mypy-1.20.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c64e5973df366b747646fc98da921f9d6eba9716d57d1db94a83c026a08e0fb", size = 13742945, upload-time = "2026-04-21T17:08:34.181Z" }, + { url = "https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc", size = 14706163, upload-time = "2026-04-21T17:05:15.51Z" }, + { url = "https://files.pythonhosted.org/packages/94/97/48ff3b297cafcc94d185243a9190836fb1b01c1b0918fff64e941e973cc9/mypy-1.20.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4fef51b01e638974a6e69885687e9bd40c8d1e09a6cd291cca0619625cf1f558", size = 14938677, upload-time = "2026-04-21T17:05:39.562Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl", hash = "sha256:913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8", size = 11089322, upload-time = "2026-04-21T17:06:44.29Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/ce7ee2ba36aeb954ba50f18fa25d9c1188578654b97d02a66a15b6f09531/mypy-1.20.2-cp314-cp314-win_arm64.whl", hash = "sha256:c3bae4f855d965b5453784300c12ffc63a548304ac7f99e55d4dc7c898673aa3", size = 10017775, upload-time = "2026-04-21T17:07:20.732Z" }, + { url = "https://files.pythonhosted.org/packages/4e/a1/9d93a7d0b5859af0ead82b4888b46df6c8797e1bc5e1e262a08518c6d48e/mypy-1.20.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2de3dcea53babc1c3237a19002bc3d228ce1833278f093b8d619e06e7cc79609", size = 15549002, upload-time = "2026-04-21T17:08:23.107Z" }, + { url = "https://files.pythonhosted.org/packages/00/d2/09a6a10ee1bf0008f6c144d9676f2ca6a12512151b4e0ad0ff6c4fac5337/mypy-1.20.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:52b176444e2e5054dfcbcb8c75b0b719865c96247b37407184bbfca5c353f2c2", size = 14401942, upload-time = "2026-04-21T17:07:31.837Z" }, + { url = "https://files.pythonhosted.org/packages/57/da/9594b75c3c019e805250bed3583bdf4443ff9e6ef08f97e39ae308cb06f2/mypy-1.20.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:688c3312e5dadb573a2c69c82af3a298d43ecf9e6d264e0f95df960b5f6ac19c", size = 15041649, upload-time = "2026-04-21T17:09:34.653Z" }, + { url = "https://files.pythonhosted.org/packages/97/77/f75a65c278e6e8eba2071f7f5a90481891053ecc39878cc444634d892abe/mypy-1.20.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29752dbbf8cc53f89f6ac096d363314333045c257c9c75cbd189ca2de0455744", size = 15864588, upload-time = "2026-04-21T17:11:44.936Z" }, + { url = "https://files.pythonhosted.org/packages/d7/46/1a4e1c66e96c1a3246ddf5403d122ac9b0a8d2b7e65730b9d6533ba7a6d3/mypy-1.20.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:803203d2b6ea644982c644895c2f78b28d0e208bba7b27d9b921e0ec5eb207c6", size = 16093956, upload-time = "2026-04-21T17:10:17.683Z" }, + { url = "https://files.pythonhosted.org/packages/5a/2c/78a8851264dec38cd736ca5b8bc9380674df0dd0be7792f538916157716c/mypy-1.20.2-cp314-cp314t-win_amd64.whl", hash = "sha256:9bcb8aa397ff0093c824182fd76a935a9ba7ad097fcbef80ae89bf6c1731d8ec", size = 12568661, upload-time = "2026-04-21T17:11:54.473Z" }, + { url = "https://files.pythonhosted.org/packages/83/01/cd7318aa03493322ce275a0e14f4f52b8896335e4e79d4fb8153a7ad2b77/mypy-1.20.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e061b58443f1736f8a37c48978d7ab581636d6ab03e3d4f99e3fa90463bb9382", size = 10389240, upload-time = "2026-04-21T17:09:42.719Z" }, + { url = "https://files.pythonhosted.org/packages/28/9a/f23c163e25b11074188251b0b5a0342625fc1cdb6af604757174fa9acc9b/mypy-1.20.2-py3-none-any.whl", hash = "sha256:a94c5a76ab46c5e6257c7972b6c8cff0574201ca7dc05647e33e795d78680563", size = 2637314, upload-time = "2026-04-21T17:05:54.5Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packageurl-python" +version = "0.17.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/d6/3b5a4e3cfaef7a53869a26ceb034d1ff5e5c27c814ce77260a96d50ab7bb/packageurl_python-0.17.6.tar.gz", hash = "sha256:1252ce3a102372ca6f86eb968e16f9014c4ba511c5c37d95a7f023e2ca6e5c25", size = 50618, upload-time = "2025-11-24T15:20:17.998Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/2f/c7277b7615a93f51b5fbc1eacfc1b75e8103370e786fd8ce2abf6e5c04ab/packageurl_python-0.17.6-py3-none-any.whl", hash = "sha256:31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9", size = 36776, upload-time = "2025-11-24T15:20:16.962Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pathspec" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, +] + +[[package]] +name = "pip" +version = "26.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/91/47e7d486260f618783899587af63ccf7980fb60245c3e63dd4571c6b57ad/pip-26.1.2.tar.gz", hash = "sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605", size = 1840799, upload-time = "2026-05-31T17:33:58.56Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl", hash = "sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab", size = 1813144, upload-time = "2026-05-31T17:33:56.772Z" }, +] + +[[package]] +name = "pip-api" +version = "0.0.34" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pip" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/f1/ee85f8c7e82bccf90a3c7aad22863cc6e20057860a1361083cd2adacb92e/pip_api-0.0.34.tar.gz", hash = "sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625", size = 123017, upload-time = "2024-07-09T20:32:30.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/f7/ebf5003e1065fd00b4cbef53bf0a65c3d3e1b599b676d5383ccb7a8b88ba/pip_api-0.0.34-py3-none-any.whl", hash = "sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb", size = 120369, upload-time = "2024-07-09T20:32:29.099Z" }, +] + +[[package]] +name = "pip-audit" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachecontrol", extra = ["filecache"] }, + { name = "cyclonedx-python-lib" }, + { name = "packaging" }, + { name = "pip-api" }, + { name = "pip-requirements-parser" }, + { name = "platformdirs" }, + { name = "requests" }, + { name = "rich" }, + { name = "tomli" }, + { name = "tomli-w" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/a4/f21d5f0a0edabcbce31560b73c7c5a6f72ae87af4236fd1069c8f59a353d/pip_audit-2.10.1.tar.gz", hash = "sha256:1eb4565d19ebe5d48996f4b770b4d2b32887e12cb12cfa637f1a064011b55ffc", size = 54275, upload-time = "2026-06-10T22:17:01.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/a7/b0c504148114047bd1bc9d97447453c6850ca176bb2f3c0038835994e8b7/pip_audit-2.10.1-py3-none-any.whl", hash = "sha256:99ef3f600a317c1945f1e89e227ef26e1c2d618429b8bd3fa6f4f7c440c4611a", size = 62023, upload-time = "2026-06-10T22:17:00.309Z" }, +] + +[[package]] +name = "pip-requirements-parser" +version = "32.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/2a/63b574101850e7f7b306ddbdb02cb294380d37948140eecd468fae392b54/pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3", size = 209359, upload-time = "2022-12-21T15:25:22.732Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/d0/d04f1d1e064ac901439699ee097f58688caadea42498ec9c4b4ad2ef84ab/pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526", size = 35648, upload-time = "2022-12-21T15:25:21.046Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/cd/4f25b2f95b23f5d2c9c1fe43e49841bff5800562149b2666afc09309aa8f/platformdirs-4.10.1.tar.gz", hash = "sha256:ceab4084426fe6319ce18e86deada8ab1b7487c7aee7040c55e277c9ae793695", size = 31678, upload-time = "2026-07-18T03:53:43.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/73/6fd0bb9ce84138c3857f12e9de63bc901852975a092d545f18087a204aa2/platformdirs-4.10.1-py3-none-any.whl", hash = "sha256:0e4eff26be2d75293977f7cddc153fd9b8eaa7fb0c7b64ffe4076cb443117443", size = 22906, upload-time = "2026-07-18T03:53:42.576Z" }, +] + +[[package]] +name = "playwright" +version = "1.61.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet" }, + { name = "pyee" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/ee/31e4e0db36588b817a10b299a0285082545fde7d36543c2abe498bb3d61a/playwright-1.61.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:ff138c3a604f69911e9d42fd036e55c2a171e5616edf04c1e7f60a2a285540b0", size = 43421877, upload-time = "2026-06-29T10:32:48.428Z" }, + { url = "https://files.pythonhosted.org/packages/42/35/71395dd3ecc798965be4a3ef8c443217d4abca168e7cb34536304f9489e6/playwright-1.61.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:009588c2a7e499bc5a8b425b61fa65490968bbda9cd69e0cf2cff10f8304659a", size = 42205016, upload-time = "2026-06-29T10:32:52.104Z" }, + { url = "https://files.pythonhosted.org/packages/f4/44/323164cf5cd1647bdefce76ffce27651aadb959d089b48f53ea40918276e/playwright-1.61.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:9f7de4536088d12037c13a52b7ea34b59270b78926bb56935070597ffac6b1af", size = 43421884, upload-time = "2026-06-29T10:32:55.773Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/a35bf179e4ba2522c1893635094a64e407572547bd61528820fc0abc87fe/playwright-1.61.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:54f3b39f6eab832e33458c1dd7da0b5682aedab3b09ae731b5c59fa12fd2024e", size = 47421381, upload-time = "2026-06-29T10:32:59.903Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/e3f922348ec17c315f98c463f72faa1181a1c3de0bfe31a8d2edf6561723/playwright-1.61.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93454322ade8c11d5d6c211bfd91bdfb9ffb4810e3e026371bcbc4bec1b7ee4c", size = 47120545, upload-time = "2026-06-29T10:33:03.574Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a6/5be4e52b40a9c0c8a073e7c5b0785c05cf5a9ea8f8a7b5b260e32d970342/playwright-1.61.0-py3-none-win32.whl", hash = "sha256:372d55a6f1248fa1dd47599686980cb8fb5bbe6fcda59eab793eb657c11d8a9b", size = 37844841, upload-time = "2026-06-29T10:33:07.361Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fd/2b78036e5fbe9d5f5645bbe08a1eac7160c51243c0093963edbcf67c35d9/playwright-1.61.0-py3-none-win_amd64.whl", hash = "sha256:35c6cc4589a5d00964a59d7b3e59641e0aac0c02f15479a7af77d20f6bc79597", size = 37844846, upload-time = "2026-06-29T10:33:10.637Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/1b0f3c4ee4eb0514bc805b5c2f9a223e5b6de4f11a926f5235d51d0fc81b/playwright-1.61.0-py3-none-win_arm64.whl", hash = "sha256:e9fcbffcf557a8620fdedd92491eb59a32d18e23d6f3b4f6214b952be324fe51", size = 33955127, upload-time = "2026-06-29T10:33:14.008Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035, upload-time = "2026-04-09T19:53:42.359Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154, upload-time = "2026-04-09T19:53:41.324Z" }, +] + +[[package]] +name = "psycopg" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, +] + +[[package]] +name = "psycopg-binary" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/7d/03818e13ba7f36de93573c93ee3482006d3dfa8b0f8d28df511bad0a1a92/psycopg_binary-3.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089", size = 4591122, upload-time = "2026-05-01T23:27:56.162Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b9/11b341edf8d54e2694726b273fe9652b254d989f4f63e3ac6816ad6b55f4/psycopg_binary-3.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578", size = 4669943, upload-time = "2026-05-01T23:28:04.522Z" }, + { url = "https://files.pythonhosted.org/packages/8b/18/4665bacd65e7865b4372fcd8abb8b9186ada4b0025f8c2ca691b364a556c/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9", size = 5469697, upload-time = "2026-05-01T23:28:11.337Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b1/b83136c6e510593d9b0c759ba5384337bc4ad82d19fda675adc4b2703c84/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d", size = 5152995, upload-time = "2026-05-01T23:28:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/67/8d/a9821e2a648afe6091989929982a3b0f00b2631a859cb81379728f08fb75/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b", size = 6738180, upload-time = "2026-05-01T23:28:30.654Z" }, + { url = "https://files.pythonhosted.org/packages/7e/58/2e349e8d23905dc2317b80ac65f48fb6f821a4777a4e994a60da91c4850f/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070", size = 4978828, upload-time = "2026-05-01T23:28:37.277Z" }, + { url = "https://files.pythonhosted.org/packages/45/48/57b00d03b4721878326122a1f1e6b0a90b85bcaec56b5b2f8ea6cfa45235/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68", size = 4509757, upload-time = "2026-05-01T23:28:43.078Z" }, + { url = "https://files.pythonhosted.org/packages/25/37/33b47d8c007df69aec500df5889767c4d313748e8e9e27a2fef8a6dabcee/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16", size = 4190546, upload-time = "2026-05-01T23:28:50.016Z" }, + { url = "https://files.pythonhosted.org/packages/ca/c6/32b0835dbc2122617902b649d76a91c1e75406e76bf3d595b0c3bb5ffad6/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652", size = 3926197, upload-time = "2026-05-01T23:28:55.55Z" }, + { url = "https://files.pythonhosted.org/packages/cd/68/d190ef0c0c5b16ded07831dabc8ddd412f4cdab07ec6e30ed38d9bda0e1f/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e", size = 4236627, upload-time = "2026-05-01T23:29:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/25/8f/81dcbc2e8454b74d14881275ea45f00791052dac531a9fa8be1730d1685b/psycopg_binary-3.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4", size = 3560782, upload-time = "2026-05-01T23:29:11.967Z" }, + { url = "https://files.pythonhosted.org/packages/09/43/13e9c406fbbf354580476e248a16b64802a376873ebe6339e30bb655572d/psycopg_binary-3.3.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7", size = 4590377, upload-time = "2026-05-01T23:29:18.782Z" }, + { url = "https://files.pythonhosted.org/packages/22/be/2923cd7c3683e7afdecf4f10796a18de02f5c5ddc0969aa2ad0a8cdd3bbd/psycopg_binary-3.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31", size = 4669023, upload-time = "2026-05-01T23:29:25.884Z" }, + { url = "https://files.pythonhosted.org/packages/96/a0/2c913d6fe13d6a8bd13597d36739bf47af063ad9399e402cfecab16f3c1e/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70", size = 5467423, upload-time = "2026-05-01T23:29:33.416Z" }, + { url = "https://files.pythonhosted.org/packages/e7/38/205d10bc1ad0df4a21c5c51659126bd3ea0ef98fcad1e852f78c249bb9c3/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3", size = 5151137, upload-time = "2026-05-01T23:29:42.013Z" }, + { url = "https://files.pythonhosted.org/packages/36/fc/f0381ddcd45eff3bb70dbca6823a996048d7f507b2ec3fc92c6fabc0fe87/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c", size = 6736671, upload-time = "2026-05-01T23:29:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/95/40/fa545ae152c24327651e5624e4902121e808270be36c10b12e9939be09bc/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae", size = 4979601, upload-time = "2026-05-01T23:29:56.961Z" }, + { url = "https://files.pythonhosted.org/packages/86/e4/2f8a47ee97f90cd2b933d0463081d35631ff419de2b8c984a5f369857de0/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc", size = 4510513, upload-time = "2026-05-01T23:30:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0e/94e842ff4a7f98ed162580ca2e8b8864b28c1e0350f2443f8ee47f821167/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf", size = 4187243, upload-time = "2026-05-01T23:30:15.352Z" }, + { url = "https://files.pythonhosted.org/packages/d0/83/fc6c174b672e29b7de996ea77b6cbddf46c891751c3355f6974292baa6b4/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260", size = 3927347, upload-time = "2026-05-01T23:30:21.186Z" }, + { url = "https://files.pythonhosted.org/packages/e9/65/768364d4a97a15b1a7f47ba52688c1686f22941d8332a8398cefc468e25f/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf", size = 4236393, upload-time = "2026-05-01T23:30:26.211Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3b/218efbc9e645becd80cdf651acda05f85cfe546b7a9c0458c7cbc8fe1f74/psycopg_binary-3.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38", size = 3564592, upload-time = "2026-05-01T23:30:31.764Z" }, + { url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" }, + { url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" }, + { url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" }, + { url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" }, +] + +[[package]] +name = "py-serializable" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "defusedxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/21/d250cfca8ff30c2e5a7447bc13861541126ce9bd4426cd5d0c9f08b5547d/py_serializable-2.1.0.tar.gz", hash = "sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103", size = 52368, upload-time = "2025-07-21T09:56:48.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/bf/7595e817906a29453ba4d99394e781b6fabe55d21f3c15d240f85dd06bb1/py_serializable-2.1.0-py3-none-any.whl", hash = "sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304", size = 23045, upload-time = "2025-07-21T09:56:46.848Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, +] + +[[package]] +name = "pyee" +version = "13.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/04/e7c1fe4dc78a6fdbfd6c337b1c3732ff543b8a397683ab38378447baa331/pyee-13.0.1.tar.gz", hash = "sha256:0b931f7c14535667ed4c7e0d531716368715e860b988770fc7eb8578d1f67fc8", size = 31655, upload-time = "2026-02-14T21:12:28.044Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/b4d4827c93ef43c01f599ef31453ccc1c132b353284fc6c87d535c233129/pyee-13.0.1-py3-none-any.whl", hash = "sha256:af2f8fede4171ef667dfded53f96e2ed0d6e6bd7ee3bb46437f77e3b57689228", size = 15659, upload-time = "2026-02-14T21:12:26.263Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] + +[[package]] +name = "pytest-cov" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/4c/f883ab8f0daad69f47efdf95f55a66b51a8b939c430dadce0611508d9e99/pytest_cov-6.3.0.tar.gz", hash = "sha256:35c580e7800f87ce892e687461166e1ac2bcb8fb9e13aea79032518d6e503ff2", size = 70398, upload-time = "2025-09-06T15:40:14.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/b4/bb7263e12aade3842b938bc5c6958cae79c5ee18992f9b9349019579da0f/pytest_cov-6.3.0-py3-none-any.whl", hash = "sha256:440db28156d2468cafc0415b4f8e50856a0d11faefa38f30906048fe490f1749", size = 25115, upload-time = "2025-09-06T15:40:12.44Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.32" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "rfc8785" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/2f/fa1d2e740c490191b572d33dbca5daa180cb423c24396b856f5886371d8b/rfc8785-0.1.4.tar.gz", hash = "sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da", size = 14321, upload-time = "2024-09-27T16:33:31.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/78/119878110660b2ad709888c8a1614fce7e2fab39080ab960656dc8605bf6/rfc8785-0.1.4-py3-none-any.whl", hash = "sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48", size = 9240, upload-time = "2024-09-27T16:33:29.683Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" }, + { url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" }, + { url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" }, + { url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" }, + { url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" }, + { url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" }, + { url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" }, + { url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" }, + { url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" }, + { url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" }, + { url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" }, + { url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" }, + { url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" }, + { url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" }, + { url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" }, + { url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" }, + { url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" }, + { url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" }, + { url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" }, + { url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" }, + { url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" }, + { url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" }, + { url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, +] + +[[package]] +name = "sqlalchemy" +version = "2.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/70/e868bc5412acd101a8280f25c95f10eeae0771c4eb806b02491142810ee8/sqlalchemy-2.0.51-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d78702b26ba1c18b2d0fb2ea940ba7f17a9581b42e8361ff93920ebbee1235a", size = 2160291, upload-time = "2026-06-15T16:08:48.918Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1c/71ee0f8a6b9d7316a1ccd30430b4c62b6c2e36adc96017a4e3a72dce49d6/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581921d849d6e6f994d560389192955e80e2950e18fcdfe2ccea863e01158e6e", size = 3343835, upload-time = "2026-06-15T16:19:42.613Z" }, + { url = "https://files.pythonhosted.org/packages/2b/7c/7ab9f9aadc5944fdd06612484ed7918fe376ad871a5f50404dc1536e0194/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d21ce524ab86c23046e992a5b81cb54c21079c6df6e78b8fc77d77cac70a6b9", size = 3358470, upload-time = "2026-06-15T16:26:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7d/ff77169fee6186de145a7f2b87006c39638391130abbab2b1f63ac6ea583/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c5d98a2709840027f5a347c3af0a7c3d5f6c1ff93af2ca1c54494e23cba8f389", size = 3289874, upload-time = "2026-06-15T16:19:45.212Z" }, + { url = "https://files.pythonhosted.org/packages/6f/3b/6c505903710d781b55bc3141ee34a062bf9745a6b5bc7333305b9ed63b33/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1181256e0f16479691b5616d36375dc2620ad8332b25978763c3d206ad3f3f1d", size = 3321692, upload-time = "2026-06-15T16:26:39.747Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b7/c5ffe50aa2f4d947c9250e1519d939260329a07fe6272edfccd784b3d007/sqlalchemy-2.0.51-cp312-cp312-win32.whl", hash = "sha256:9f380393be5abeb6815f68fd39271b95127173511b6706b0a630a9995d53f8f5", size = 2119674, upload-time = "2026-06-15T16:23:09.543Z" }, + { url = "https://files.pythonhosted.org/packages/25/dc/46a65916af68a06ef6b972c6050ba4c8f97070fe3fb33097d34229d9bef6/sqlalchemy-2.0.51-cp312-cp312-win_amd64.whl", hash = "sha256:2cf39aabdf48e87c1c2c2ed6d20d33ffa0733b3071ce9c5f66357947dd009080", size = 2146670, upload-time = "2026-06-15T16:23:11.048Z" }, + { url = "https://files.pythonhosted.org/packages/54/fe/a210d52fd1a90ecfae8a78e9d8b27e18d733d60818a8bf250ff690b75120/sqlalchemy-2.0.51-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c2056838b6685b72fdb36c99996cf862753461a62f2e84f4196371d3b2d6a07", size = 2157184, upload-time = "2026-06-15T16:08:50.374Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/2dce8369b199cb855110e056032f94a9f66dacc2237d3d39c115a86eac56/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:483b11bd46bf35fc14c52faf338b04300c9e6ce554bce9b11be85bfec3bc3195", size = 3284735, upload-time = "2026-06-15T16:19:46.934Z" }, + { url = "https://files.pythonhosted.org/packages/53/ff/dbc495b8a14da840faffb353857a72d4190113cac33727906fb997047f0f/sqlalchemy-2.0.51-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1bed1ee8b01da6088210aa9412023326fb98a599ba502e6118308601dcbef77f", size = 3302756, upload-time = "2026-06-15T16:26:41.336Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d5/fde8f4dddcf518ee15ab35a7c6a28acc32c8ba548d1d2aa451f96e6dbb0b/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:72ca54c952107ba5cd58854b67a5a6268631289d21651a1235396f3b98b47400", size = 3232055, upload-time = "2026-06-15T16:19:49.286Z" }, + { url = "https://files.pythonhosted.org/packages/67/d1/43d3a0ac955a58601c24fa23038b1c55ee3a1ec02c0f96ebb1eae2bcf614/sqlalchemy-2.0.51-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b3e693d15533a45cd5906f0589f9c35090bef6ef45bf1e8195c424aa0ae06a8d", size = 3269850, upload-time = "2026-06-15T16:26:43.017Z" }, + { url = "https://files.pythonhosted.org/packages/94/df/de669c7054cd47c4439ac34b1b2ee8b804a794791fbb10720e997a2c87c7/sqlalchemy-2.0.51-cp313-cp313-win32.whl", hash = "sha256:b93ab07b5292dbe7e6b8da89475275e7042744283921344b56105f3eeb0f828b", size = 2117721, upload-time = "2026-06-15T16:23:12.36Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8a/403c51d064196bae20a0bc2476577f83a3f8dd299719a97417086b7f2ec5/sqlalchemy-2.0.51-cp313-cp313-win_amd64.whl", hash = "sha256:0f053118c30e53161857a953e4de667d90e274980dccbe5dd3829bbbeece72a5", size = 2143615, upload-time = "2026-06-15T16:23:13.906Z" }, + { url = "https://files.pythonhosted.org/packages/b1/49/a739be2e1d02a96a658eb71ab45d921c874249252358ad24a5bffdd02525/sqlalchemy-2.0.51-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6ea306caaae6bd5afd0a46050003c88f6bf33227377a49298c498c3cb88ff491", size = 2158999, upload-time = "2026-06-15T16:08:51.759Z" }, + { url = "https://files.pythonhosted.org/packages/23/6b/2e0e38cf75c8780eca78d9b2e78164f8bcfd70125e5caa588ff5cbb9c9f4/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c45a496d6bc05dec41dcd4c3a2b183723f47473255c159cd80b503c8f246424d", size = 3282539, upload-time = "2026-06-15T16:19:51.065Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a1/e77854cb5336fd37dc3c6ae3b71de242c98caac5725120be0b526b31cbd0/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4004ada0aafe8ae1991b2cd1d99c6d9146126e123bd6f883c260d974aa012e54", size = 3287545, upload-time = "2026-06-15T16:26:44.735Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ab/9e17272fd4dac8df3b83c4fbe52b998a1c9d89a843c8c35ff29b74ff7364/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f6bcad487aee1c638d707235682fc96f741de00663619881ab235400d03289e", size = 3230929, upload-time = "2026-06-15T16:19:52.625Z" }, + { url = "https://files.pythonhosted.org/packages/02/3c/52f408ea701781caee975606beccc48845f2aee8711ac29843d612c0306c/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:39a76529db6305693d8d4affa58ad5b5e2e18edd62daea628b29b97930b3513d", size = 3252888, upload-time = "2026-06-15T16:26:46.454Z" }, + { url = "https://files.pythonhosted.org/packages/24/16/3efd2ee6bc4ca4693a30a1dd17a91b606cae15d517d2a4746611d9b73ce8/sqlalchemy-2.0.51-cp314-cp314-win32.whl", hash = "sha256:08a204d8b5638717c26a24df18fcf40af45a6b22e35b70b1d62f0113c2e278e8", size = 2120551, upload-time = "2026-06-15T16:23:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/7b/78/55b12e70f45bccc40d9e483925c065027b3b98ea4cbbdf6f8c2546feaf6c/sqlalchemy-2.0.51-cp314-cp314-win_amd64.whl", hash = "sha256:96747bfbadb055466e5b46d572618170046b45ce5a4879167f50d70a5319a499", size = 2146318, upload-time = "2026-06-15T16:23:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/21/db/a9574ed40fed418924b1b1a3e54f47ee3963053b3d3d325a0d36b41f2c08/sqlalchemy-2.0.51-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1a213be1fcd5e49d9904c3b9939211ded90bc2a64e93f4c01963474285de", size = 2178920, upload-time = "2026-06-15T15:59:56.285Z" }, + { url = "https://files.pythonhosted.org/packages/bf/90/a1bb5c7cbba76b7bc1fbd586d0a5479a7bc9c27b4a8298f22ec9423b2bb3/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c6b36ed71f41942bdcd2ad2522be46bfce09d5705be5640ecf19bbc7660e4b7", size = 3566534, upload-time = "2026-06-15T15:58:35.024Z" }, + { url = "https://files.pythonhosted.org/packages/15/4b/481f1fed30e0e9e8dd24aecbb49f29eb57fe7657ece5cf06ee9b84bb97d8/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2c62877097e1a0db401fba5cb4debee33265e5b2a55c4ccb489c02c53b4f72", size = 3535844, upload-time = "2026-06-15T16:02:43.973Z" }, + { url = "https://files.pythonhosted.org/packages/02/71/0aa64aeda645510af0a43f7d9ee70932f0d1dc4263aed34c50ee891d9df3/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0378d055e9e8cd6ce4d8dff683bdd3d7d413533c4ee51d67a2b1e0f9eacc0f23", size = 3475355, upload-time = "2026-06-15T15:58:36.592Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/6061db32316446135a3abae5f308d144ab988a34234726042da3e58b1c63/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6e46fc36029eff666391e0531e5387b62ce6c4f1d8e50b3fb3099eaca1b42522", size = 3486591, upload-time = "2026-06-15T16:02:45.346Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c9/f14fdf71bb8957e0c7e39db69bbdf12b5c80f4ef775fdfa127bf4e0d6760/sqlalchemy-2.0.51-cp314-cp314t-win32.whl", hash = "sha256:9161cfc9efce70d1715f47d6ff40f79c6778c00d53be4fbc09d70301e4b83ba7", size = 2151313, upload-time = "2026-06-15T16:03:39.127Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/673e618e6f4f297e126d9b56ea2f6478708f6c1af4e3223835c22e2c3697/sqlalchemy-2.0.51-cp314-cp314t-win_amd64.whl", hash = "sha256:159bb6ba32059f57ad7375a8f50d844dd2f19d14954ecf820cd33e20debd46b2", size = 2186280, upload-time = "2026-06-15T16:03:40.569Z" }, + { url = "https://files.pythonhosted.org/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, +] + +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, +] + +[[package]] +name = "types-jsonschema" +version = "4.26.0.20260518" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/46/73b6a5d61a61015c4248030a8cb07e5bdddb4041430fae9e585a68692578/types_jsonschema-4.26.0.20260518.tar.gz", hash = "sha256:e1dd53dc97a64f5eccdd6fa9839666e09bb500a8ebba2db6fdaf1789faea81a6", size = 16638, upload-time = "2026-05-18T06:06:44.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/d5/134f8a147dcecda10db7f60cfc6af0578a25a5c53c87b3907a64385e0184/types_jsonschema-4.26.0.20260518-py3-none-any.whl", hash = "sha256:30b30a518c7fe335df85c919fcbcc631b69c03d4a4b5b632fa916bea03065307", size = 16072, upload-time = "2026-05-18T06:06:43.264Z" }, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20260518" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/83/4a1afc3fbfcf5b8d46fc390cd95ed6b0dc9010a265f4e9f46314efffa37a/types_pyyaml-6.0.12.20260518.tar.gz", hash = "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466", size = 17850, upload-time = "2026-05-18T06:01:58.675Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/a2/c01db32be2ae7d6a1689972f3c492b149ee4e164b12fdfd9f64b50888215/types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash = "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd", size = 20312, upload-time = "2026-05-18T06:01:57.368Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.51.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/ec/dbb7e5a6b91f86bfb9eb7d2988a2730907b6a729875b949c7f022e8b88fa/uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b", size = 73219, upload-time = "2026-07-08T10:59:04.44Z" }, +] + +[package.optional-dependencies] +standard = [ + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.22.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/ff/7f72e8170be527b4977b033239a83a68d5c881cc4775fca255c677f7ac5d/uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42", size = 1359936, upload-time = "2025-10-16T22:16:29.436Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c6/e5d433f88fd54d81ef4be58b2b7b0cea13c442454a1db703a1eea0db1a59/uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6", size = 752769, upload-time = "2025-10-16T22:16:30.493Z" }, + { url = "https://files.pythonhosted.org/packages/24/68/a6ac446820273e71aa762fa21cdcc09861edd3536ff47c5cd3b7afb10eeb/uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370", size = 4317413, upload-time = "2025-10-16T22:16:31.644Z" }, + { url = "https://files.pythonhosted.org/packages/5f/6f/e62b4dfc7ad6518e7eff2516f680d02a0f6eb62c0c212e152ca708a0085e/uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4", size = 4426307, upload-time = "2025-10-16T22:16:32.917Z" }, + { url = "https://files.pythonhosted.org/packages/90/60/97362554ac21e20e81bcef1150cb2a7e4ffdaf8ea1e5b2e8bf7a053caa18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2", size = 4131970, upload-time = "2025-10-16T22:16:34.015Z" }, + { url = "https://files.pythonhosted.org/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" }, + { url = "https://files.pythonhosted.org/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" }, + { url = "https://files.pythonhosted.org/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" }, + { url = "https://files.pythonhosted.org/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" }, + { url = "https://files.pythonhosted.org/packages/15/c0/0be24758891ef825f2065cd5db8741aaddabe3e248ee6acc5e8a80f04005/uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e", size = 4366890, upload-time = "2025-10-16T22:16:40.547Z" }, + { url = "https://files.pythonhosted.org/packages/d2/53/8369e5219a5855869bcee5f4d317f6da0e2c669aecf0ef7d371e3d084449/uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e", size = 4119472, upload-time = "2025-10-16T22:16:41.694Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" }, + { url = "https://files.pythonhosted.org/packages/90/cd/b62bdeaa429758aee8de8b00ac0dd26593a9de93d302bff3d21439e9791d/uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142", size = 1362067, upload-time = "2025-10-16T22:16:44.503Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f8/a132124dfda0777e489ca86732e85e69afcd1ff7686647000050ba670689/uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74", size = 752423, upload-time = "2025-10-16T22:16:45.968Z" }, + { url = "https://files.pythonhosted.org/packages/a3/94/94af78c156f88da4b3a733773ad5ba0b164393e357cc4bd0ab2e2677a7d6/uvloop-0.22.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35", size = 4272437, upload-time = "2025-10-16T22:16:47.451Z" }, + { url = "https://files.pythonhosted.org/packages/b5/35/60249e9fd07b32c665192cec7af29e06c7cd96fa1d08b84f012a56a0b38e/uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25", size = 4292101, upload-time = "2025-10-16T22:16:49.318Z" }, + { url = "https://files.pythonhosted.org/packages/02/62/67d382dfcb25d0a98ce73c11ed1a6fba5037a1a1d533dcbb7cab033a2636/uvloop-0.22.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6", size = 4114158, upload-time = "2025-10-16T22:16:50.517Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/f1171b4a882a5d13c8b7576f348acfe6074d72eaf52cccef752f748d4a9f/uvloop-0.22.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079", size = 4177360, upload-time = "2025-10-16T22:16:52.646Z" }, + { url = "https://files.pythonhosted.org/packages/79/7b/b01414f31546caf0919da80ad57cbfe24c56b151d12af68cee1b04922ca8/uvloop-0.22.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289", size = 1454790, upload-time = "2025-10-16T22:16:54.355Z" }, + { url = "https://files.pythonhosted.org/packages/d4/31/0bb232318dd838cad3fa8fb0c68c8b40e1145b32025581975e18b11fab40/uvloop-0.22.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3", size = 796783, upload-time = "2025-10-16T22:16:55.906Z" }, + { url = "https://files.pythonhosted.org/packages/42/38/c9b09f3271a7a723a5de69f8e237ab8e7803183131bc57c890db0b6bb872/uvloop-0.22.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c", size = 4647548, upload-time = "2025-10-16T22:16:57.008Z" }, + { url = "https://files.pythonhosted.org/packages/c1/37/945b4ca0ac27e3dc4952642d4c900edd030b3da6c9634875af6e13ae80e5/uvloop-0.22.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21", size = 4467065, upload-time = "2025-10-16T22:16:58.206Z" }, + { url = "https://files.pythonhosted.org/packages/97/cc/48d232f33d60e2e2e0b42f4e73455b146b76ebe216487e862700457fbf3c/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88", size = 4328384, upload-time = "2025-10-16T22:16:59.36Z" }, + { url = "https://files.pythonhosted.org/packages/e4/16/c1fd27e9549f3c4baf1dc9c20c456cd2f822dbf8de9f463824b0c0357e06/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e", size = 4296730, upload-time = "2025-10-16T22:17:00.744Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/41/5e1a4bb12aac5f1493fa1bdc11154eca3b258ca4eba65d39c473fe19d8e9/watchfiles-1.2.0.tar.gz", hash = "sha256:c995fba777f1ea992f090f9236e9284cf7a5d1a0130dd5a3d82c598cacd76838", size = 108252, upload-time = "2026-05-18T04:32:04.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/2f/e42c992d2afda3108ea1c02acecc991b9f31d05c14adc2a7cee9ee211fc4/watchfiles-1.2.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:bc13eb17538be00c874699dc0abe4ee2bc8d50bb1166a6b9e175ef3fd7eb8f26", size = 400115, upload-time = "2026-05-18T04:32:02.06Z" }, + { url = "https://files.pythonhosted.org/packages/5f/8f/6af2ea19065c91d8b0ea3516fdfc8c0d349f407e8e9fbf4e5a17360de8ad/watchfiles-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d95ddc1eb6914154253d239089900813f6a767e174b8e6a50e7fdacb7e4236c", size = 393659, upload-time = "2026-05-18T04:30:50.951Z" }, + { url = "https://files.pythonhosted.org/packages/13/01/b32a967c56fb3e3e5be3db52c3d3b87fa4513aa367d8ed1ad96d42952e5f/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f70d8b291ef6e88d19b1f297a6905ddb978888d9272b0d05e6f53309856bcfc", size = 453207, upload-time = "2026-05-18T04:31:04.231Z" }, + { url = "https://files.pythonhosted.org/packages/04/98/97557a812180338cb1abd32e1cffcc4588f59b5f23e0cb006b2ba95ba64a/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56d8641cf834c2836922899105bd3ce3d0dfc69291d52edf0b4d0436829b34c0", size = 459273, upload-time = "2026-05-18T04:31:50.377Z" }, + { url = "https://files.pythonhosted.org/packages/e8/a8/b4b08dcb7653b8087c6586f7ce649505900e866bbcfe40dc9587af02e686/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2581a94056e55d7d0a31a823ea92bf73749c489ca2285bfdc0fbe6b2bb49d50c", size = 489927, upload-time = "2026-05-18T04:31:42.485Z" }, + { url = "https://files.pythonhosted.org/packages/50/94/3dceea03545d2e5ddfd839f0ddd5e1cecbf1697b5a428d5ba11cef6af95d/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41bc1199f7523b3f82843c88cbb979180c949caef0342cf90968f178e5d49b01", size = 570476, upload-time = "2026-05-18T04:31:03.071Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f2/d39a5450c3532092b91f81d274360e613c2371bc874a89c7a1a3c5e8d138/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7571e4464cb6e434958f867f7f730b8ab0b75e3f8e5eac0499168486ab3c33a8", size = 465650, upload-time = "2026-05-18T04:30:12.701Z" }, + { url = "https://files.pythonhosted.org/packages/22/24/ed72f68cbc1333ca9b9f2200aa048bb6658ae41709bc1caad4310f4bdffd/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e53a384f76b631c3ae5334ce6a52f0baa3a911eb94a4eac7f160079868b716d5", size = 456398, upload-time = "2026-05-18T04:30:13.784Z" }, + { url = "https://files.pythonhosted.org/packages/0d/64/982ef4a4e5bab5b6e5b6becc8cd5e732f6130a78b855f0abec6439a9a135/watchfiles-1.2.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:d20029a60a71a052a24c4db7673bc4de39ab89adbaccbfb5d67987c5d73f424d", size = 465140, upload-time = "2026-05-18T04:31:52.111Z" }, + { url = "https://files.pythonhosted.org/packages/a0/0c/95282abf4ed680b6096010bcfc30c5fa7a041fc5aa5a2ad17a2cc6c75bba/watchfiles-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2cb93af48550faf1cea04c303107c8b75833de7013e57ce27d3b8d21d8d0f58c", size = 630259, upload-time = "2026-05-18T04:31:25.676Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/607c1de1530c4bdcf2cf1d1ecc2505ddba5d96bd43ba9f2b0e79876f850f/watchfiles-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2995c176de7692b86a2e4c58d9ec718f753150a979cb4a754e2b4ffa38e70906", size = 659859, upload-time = "2026-05-18T04:30:24.333Z" }, + { url = "https://files.pythonhosted.org/packages/fa/08/d9e2e0f9e8e6791d33aefc694ad7eefa7f901f63caff84a81ded38692f9c/watchfiles-1.2.0-cp312-cp312-win32.whl", hash = "sha256:7a2cffd17d27d2ecbb310c2b1d8174f222a5495b1a721894afa88ec11e25b898", size = 275480, upload-time = "2026-05-18T04:30:31.307Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e6/9d42569c0102645cc8cea5d8c7d8a1e9d4ada2cb7f05f75e554b8aa2202a/watchfiles-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f155b3a1b2a5fc89cdc70d47ee5d54e3b75e88efa34982028a35daef9ba00379", size = 288718, upload-time = "2026-05-18T04:32:10.745Z" }, + { url = "https://files.pythonhosted.org/packages/0a/26/88e0dc6ee3898169d7fa22bb6a69cabf2502d2ee25cb8c876d1262d204f8/watchfiles-1.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:8fa585ede612ee9f9e91b18bebf9ba11b9ae29a4e3a0d0cf6fca3e382133f0d5", size = 281026, upload-time = "2026-05-18T04:30:22.23Z" }, + { url = "https://files.pythonhosted.org/packages/d1/4d/70a7feced9f87e2ff26dba42667290f41694fc64646c67261fbb8cab5d5c/watchfiles-1.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:01ea8d66f0693b9b60a6541c8d10263091ca9a9060d242f3c1f3143f9aad2c98", size = 399730, upload-time = "2026-05-18T04:31:38.162Z" }, + { url = "https://files.pythonhosted.org/packages/31/3a/0da302f2307aee316922806ebd5726c542cbd787c938271cf14a074c7daf/watchfiles-1.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ba0480b9a74af058f43b337e937a451e109295c420916d68ad24e3dc02f5e44", size = 392842, upload-time = "2026-05-18T04:30:27.051Z" }, + { url = "https://files.pythonhosted.org/packages/db/ef/d5bdb705c224dbc256aa0c1ec47bf4e61ec52558f2afb44a71a1fe4d7015/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f34e26a19f91f710c08e0183429f0d1d15df734e6bc78c31e77b9ea9c433658", size = 452989, upload-time = "2026-05-18T04:31:11.945Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/5495f2c1661949ef7a35e4d71111d129cfe7606414a26887a919d0a55406/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4e77f6a55f858504069abd35d336a637555c09bca453dde1ee1e5ada8a6a1fb", size = 458978, upload-time = "2026-05-18T04:30:52.606Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/7f9c07c433811c2fffd93e13fdfb7135de9aab5f2ae41be08960fa0047dc/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cb4d80e212f116474a545c21c912b445f16bb0cef9e6a73a498164223e14e2f", size = 490248, upload-time = "2026-05-18T04:31:36.003Z" }, + { url = "https://files.pythonhosted.org/packages/3c/11/d93632febc52fbc21be90231bb7c17fd5387f46c9076fd40a5f9c2ae6910/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b974946a10af379d425e2eef5b62f5c6ebeaccf91d45eaad6f5b27ecd4f91aa0", size = 571847, upload-time = "2026-05-18T04:31:10.862Z" }, + { url = "https://files.pythonhosted.org/packages/55/b4/383173e73aabb07ad1d9c7aa859d95437ac46a6d6a1e11005facda0c9d19/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86bc13c25a8d1fcd70b51d0ce7c9b65e90de5666fcbfd3e34957cc73ee19aeb5", size = 465974, upload-time = "2026-05-18T04:30:17.006Z" }, + { url = "https://files.pythonhosted.org/packages/a7/6c/89b1a230a78f57c52dd8893adb1f92f94411721b6ec12596c56d98c74356/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca148d73dea36c9763aaa351e4d7a51780ec1584217c45276f4fe8239c768b71", size = 454782, upload-time = "2026-05-18T04:30:35.656Z" }, + { url = "https://files.pythonhosted.org/packages/24/62/1732118367cfff0a9fce3bf62ff4bfded09ef5df21d9d446b858b3f70a96/watchfiles-1.2.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:c525543d91961c6955b2636b308569e84a1d1c5f5f2932041ab9ef46422f43e3", size = 465182, upload-time = "2026-05-18T04:30:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/28/96/716f7e5f51339bf22963f3345f9f27d7f3b30e2eadc597e257c881dd3c53/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a204794696ffb8f9b10fba6f7cb5216d42f3b2b71860ccac6b6e42f5f10973b0", size = 629841, upload-time = "2026-05-18T04:31:05.397Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/c40783950fd771ccf66ab3ec2722d188a9af1c7f96c6e811f36e40c6e03f/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:10d86db20695afe7997ac9e1717637d6714a8d0220458c33f3d2061f54cec427", size = 658028, upload-time = "2026-05-18T04:31:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/71/72/4508db1856d1d87fcbb3b63f4839bab1b5682cb0e8d224d122263c09654a/watchfiles-1.2.0-cp313-cp313-win32.whl", hash = "sha256:eb283ee99e21ad6443c8cdb06ac5b34b1308c329cbdf03fa02b445363714c799", size = 275183, upload-time = "2026-05-18T04:30:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/f9/36/14b76ca57652e5cc5fd1c11f32a261292c08a0d19a00351013c2549cbfb2/watchfiles-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a0f27f01bee51861392bb6b7c4fdb290b27d1eb194e9e28788d68102a0e898d9", size = 288059, upload-time = "2026-05-18T04:32:07.937Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8d/0a85e395398d8d20fadfe5c5d32c726eee17a519e78fb356f2cf7531bffe/watchfiles-1.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:3651aa7058595e9cfb75d35dd5ada2bf9f48a5b8a0f3562821d3e210c507e077", size = 280186, upload-time = "2026-05-18T04:31:54.484Z" }, + { url = "https://files.pythonhosted.org/packages/37/68/36db056f1fdcc5f07302f56e631774d6835bcd6fa3ace402304621d5f9e5/watchfiles-1.2.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:faea288b6f0ab1902ef08f4ca6de005dccf856c4e0c4f21b8c5fce02d90a1b08", size = 399031, upload-time = "2026-05-18T04:30:44.576Z" }, + { url = "https://files.pythonhosted.org/packages/c1/64/01a9d6f66a82a5c101ce939274106cc72759d62427e153f01edd2b9f87c2/watchfiles-1.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01859b11fd9fbca670f4d5da00fbac282cfea9bd67a2125d8b2833a3b5617ea9", size = 391205, upload-time = "2026-05-18T04:30:25.413Z" }, + { url = "https://files.pythonhosted.org/packages/84/2c/0a44fe058cb4bb7b8ede6b6670698bbb7c0400740e378d00022189b7b31d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff610d7bb2256a317bb1e96f0d7862c7aa8076733ee5df0fd41bbe76a24a4f4", size = 451892, upload-time = "2026-05-18T04:32:14.005Z" }, + { url = "https://files.pythonhosted.org/packages/67/a1/351e0d56cd35e6488b5c8b4fb11a809a5bc923e8fe8fed9faf8920be0c89/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b141a4891c995a039cd89e9a49e62df1dc8a559a5d1a6e4c7106d16c12777a55", size = 458867, upload-time = "2026-05-18T04:31:22.279Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7d/9d09605187f1b838998624049fcf8bf47b73c1a3b76901fcac1782f62277/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f22943b7770483f6ea0721c6b11d022947a98eb0acae14694de034f4d0d38925", size = 490217, upload-time = "2026-05-18T04:31:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/60/5d/a17a16eccb182f04188cd308ec24b1a71a9b5c4e7098269cf35d9fa56d02/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bc6195825b7dcd217968bb1f801a60fd4c16e8eeab5bedc7fe917d7d5995ab4", size = 571458, upload-time = "2026-05-18T04:32:11.875Z" }, + { url = "https://files.pythonhosted.org/packages/d3/3d/4dd457062083ab1938e5dfd45032eb425cee2ac817287ca8ff4356183e5d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4a4b147f5dca2a5d325a06a832fb43f345751adfbc63204aec30e0d9ca965a2", size = 464707, upload-time = "2026-05-18T04:30:43.492Z" }, + { url = "https://files.pythonhosted.org/packages/c6/71/ea8c57b128f5383de74d0c7d2d9c57ad7c9a65a930c451bd25d524b295b7/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4543579a9bdb0c9560039b4ffddbdb39545707659fbc430ce4c10f3f68d557f9", size = 454663, upload-time = "2026-05-18T04:30:16.061Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/2e812bf938406d7db351f0703ddd3fc6c061cf30d96153a77bc79a943a44/watchfiles-1.2.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:20aa0e708b920bde876a4aa82dc7dd6ebea228a63a67cda6632c2fc87b787efa", size = 463537, upload-time = "2026-05-18T04:31:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/86/56/d17a7f1dd1bc3035f1072694a551301272f1739c2d8e319c927cb9e29b38/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:d413349d565dab74297f2a63e84a097936be69bf8f3b3801f27f380e32040f44", size = 629194, upload-time = "2026-05-18T04:31:14.141Z" }, + { url = "https://files.pythonhosted.org/packages/be/06/f1ff66bf5cae50aa4062779a0ecd0bbaf15e466195719074078947d9a17d/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f28b2725eb8cce327b9b3ab02415c853011dc55c95832fe90de6bc56f5315f72", size = 656194, upload-time = "2026-05-18T04:31:47.14Z" }, + { url = "https://files.pythonhosted.org/packages/e7/54/a9c7ea9a82a4ac65e7004c0a03920b5cdd2f9c3b678757d9cd425aa51d53/watchfiles-1.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b8c8358484d5fa12ef34f05b7f4168eaf1932f408725ff6d023c33ec17bd79d4", size = 400205, upload-time = "2026-05-18T04:32:05.153Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5d/c9ab3534374a4a67450696905d6ef16a04405448b8dc52bd752ae50423d4/watchfiles-1.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f04b092229ad2c50126dd3c922c8822e51e605993764a33058d4a791ab42281", size = 392508, upload-time = "2026-05-18T04:30:54.849Z" }, + { url = "https://files.pythonhosted.org/packages/26/ca/1ad30103535cf0cecd7b993e8d50edc5351b1820e38f2d22e3df58962feb/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a7ce236284f002a156f70add88efe5c70879cccbb658be0822c54b1306fc09d", size = 452448, upload-time = "2026-05-18T04:30:53.727Z" }, + { url = "https://files.pythonhosted.org/packages/37/a1/ceee2cdf2afbd715fa07758d39c9859513eae411b23196f7fd039e5feedd/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b9909cc2b48468b575eefa944919e1fe8a36c5849d5c7c168f80a8c1db69398e", size = 459605, upload-time = "2026-05-18T04:30:23.312Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f6/421e30fd1cb3907a84ed92ab3f1983e37ba2dca015e9a894a048418417a2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a37faaed405c67e28e6be45a1fa4f206ef5a2860f27c237db9fa30704c38242", size = 490757, upload-time = "2026-05-18T04:30:47.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/55ed1b97ed08be7bba6f9a541cac15f2a858e1d74d2b07b6da70a82aab00/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9649193aa27bd9ff2e80ff29bfaa93085496c7a3a377592823cc58b77ee88add", size = 568672, upload-time = "2026-05-18T04:30:38.915Z" }, + { url = "https://files.pythonhosted.org/packages/d1/cf/d8ae8a80dd7bafab395ea7681c10237311bbf34d37704a8c744e7cf31fc7/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e4ff8e37f99cf1da89e255e07c9c4b37c214038c4283707bdec308cb1b0ea1f", size = 464197, upload-time = "2026-05-18T04:30:09.914Z" }, + { url = "https://files.pythonhosted.org/packages/7c/8a/3076c496ca8dafe0e8cd03fcebdfc47be4b1174b4e5b24ff6e396e6b3af2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:054dc20fd2e3132b4c3883b4a00d72fd6e1f56fdaf89fccd12e8057d74cd74d7", size = 453181, upload-time = "2026-05-18T04:30:14.829Z" }, + { url = "https://files.pythonhosted.org/packages/e5/10/9745e17c98e7b8a86454df0a3c7b5686bd650383f1e9f26e4ebcbd6cc0c0/watchfiles-1.2.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e140ed30ebde76796b686e67c182cff10ea2fbab186fafd1560f74bb5a473a6e", size = 465109, upload-time = "2026-05-18T04:30:28.123Z" }, + { url = "https://files.pythonhosted.org/packages/8f/95/8ef4a95481d3e0cb52d62a06fa6e972e81424be2d9698b91a2fecca9904c/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:bb7e52ecf68ba46d22df23467b87cffeb2146908aa523ebfe803019618cfda06", size = 630653, upload-time = "2026-05-18T04:31:49.304Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e4/3b3bf36b0f829b50c6ebcb8d031583863c59f923d6a6af3d485e470d0fac/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:23282a321c8baf9b3a3c4afff673f9fe65eb7fdc2338d765ccad9d3d1916a5ba", size = 657838, upload-time = "2026-05-18T04:31:06.497Z" }, + { url = "https://files.pythonhosted.org/packages/21/b1/6cbbb50c1f3002ab568777d44aa21206dfb8807a840990c4037523b51812/watchfiles-1.2.0-cp314-cp314-win32.whl", hash = "sha256:c0db965c5f79aa49fe672d297cf1febc5ad149b658594944f49a54a2b96270a7", size = 275108, upload-time = "2026-05-18T04:30:06.891Z" }, + { url = "https://files.pythonhosted.org/packages/92/45/190ce6db8dcb4536682cf75d3889ff1a27182a58cb519d343cb6d9ea63d8/watchfiles-1.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:71283b39fd17e5408eb123bd37aeecfd9d54c81fc184421943208aadb879d103", size = 288441, upload-time = "2026-05-18T04:32:12.901Z" }, + { url = "https://files.pythonhosted.org/packages/74/0d/3eae1c2313ab08378431d907c3f8095ecca00f3eda33111cf4f0f2591799/watchfiles-1.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:c5c19526f4e54a00f2666a6c0e9e40d582c09e865055ea7378bf0009aab857b3", size = 280684, upload-time = "2026-05-18T04:31:26.902Z" }, + { url = "https://files.pythonhosted.org/packages/b1/75/fb64e6c25d6b5ca636d03df34ffb1c6e9873303e76d27967e045f8df088f/watchfiles-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d73a585accffa5ae39c17264c36ec3166d2fad7000c780f5ef83b2722afb9dd2", size = 398857, upload-time = "2026-05-18T04:32:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/73/4e/9f7adf01754cbf81843722ccfec169d8f26c69778281a302855cecd2ee08/watchfiles-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ae99b14c5f21e026e0e9d96f40e07d8570ebee6cafd9d8fc318354606daa7a28", size = 392413, upload-time = "2026-05-18T04:31:07.911Z" }, + { url = "https://files.pythonhosted.org/packages/47/c8/bec626bcc2d69f44b9acb24ce7d60ed7b16b73628eea747fcbd169d8edda/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4429f3b105524a10b72c3a819b091c495d2811d419c1e1e8df773a5a5974f831", size = 452409, upload-time = "2026-05-18T04:31:20.142Z" }, + { url = "https://files.pythonhosted.org/packages/00/b7/b6362068e81e7c556d155a34c35d40ac3ef42d747b06d7f6e5bf58e359c2/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d818978d06062d9b22c4fab2ebe44cf5213d42dc8e62bda8c2760cfa2eeb33", size = 458827, upload-time = "2026-05-18T04:32:06.219Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/9a813fa42afb1e0b4625e75f0479826644d3ee8dc287e093799bc01f390c/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9f732dc58b2dbe69e464ccf8fff7a03b0dd0be439da4c0720d3558527d3d6b4", size = 490104, upload-time = "2026-05-18T04:31:56.034Z" }, + { url = "https://files.pythonhosted.org/packages/2f/bf/27dfb6094ca4c9aad21298b5525b6c53cb36121ee454331d05161e58d130/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f200104103feb097de4cab8fe4f5dd18a2026934c7dea98c55a2f5fd6d5a33b", size = 571360, upload-time = "2026-05-18T04:31:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/fb/39/44a096d67270ea93df91d33877dbe91fbda3aa4f8ec2edf799d93eda8736/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ac26eefbf4af1741247d6fb68b11c49a25b2f7413fbd318a83a12aaa9cf666", size = 464644, upload-time = "2026-05-18T04:30:57.33Z" }, + { url = "https://files.pythonhosted.org/packages/0e/80/c7472203bad6268e3ef1ad260739704847898938ad7ea8b63a5131f46b50/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c4997d4e4a55f0d02b6cde327322daf3a0400e5df6c6b15948994bf72497925", size = 454771, upload-time = "2026-05-18T04:30:48.736Z" }, + { url = "https://files.pythonhosted.org/packages/51/cf/3b10b268b4b7f0fc26e9debb5eef1998b515887840f444cd3ec80c688755/watchfiles-1.2.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4c887eba18b7945ac73067a8b4a66f21cd46c2539b2bc68588f7be6c7eb6d26b", size = 463494, upload-time = "2026-05-18T04:31:33.826Z" }, + { url = "https://files.pythonhosted.org/packages/3d/3e/a4302545cd589262a0dc7d140e86f7688eba3f9c72776c27f7e23b8864c4/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:3416ff151bb6b5a8d8d11664974fbef4d9305b9b2957839ab5a270468fd8df30", size = 629383, upload-time = "2026-05-18T04:31:15.596Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/d5649df0a9a410d45b7c882304d0b790903ac9b6e8f2cfd12114e0c6b9f2/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:0e831a271c035d89789cffc386b6aa1375f39f1cd25eb7ca0997e4970d152fc5", size = 656093, upload-time = "2026-05-18T04:31:58.707Z" }, +] + +[[package]] +name = "websockets" +version = "16.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/f7/bc3a25c5ec26ce62ce487690becc2f3710bbc7b33338f005ad390db0b986/websockets-16.1.1.tar.gz", hash = "sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57", size = 182204, upload-time = "2026-07-17T22:51:05.858Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/9d/681cda21c9eee743203a6cb79b9d3d05adad9aa60ec660c6c9bf4dd619ca/websockets-16.1.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cc97814dfb786a83b6e2dc2e79351e1b83e6d715647d6887fcabd83026417a00", size = 179600, upload-time = "2026-07-17T22:49:13.92Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8d/6195a88b45e8d2a8f745fc2046e36f885a3c9763e6767d2c46229bf9510c/websockets-16.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e047dc87ef7ca50f4d309bf775ad4a71711c58556d75d7bd0604b2317f43e94b", size = 177272, upload-time = "2026-07-17T22:49:15.453Z" }, + { url = "https://files.pythonhosted.org/packages/73/e3/fe2d498c64dea0095c9a9f9a351af4cd6eef31b618395582bc1f38ba45ff/websockets-16.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01fbdcbac298efe19360b94bc0039c8f746f0220ba570f327577bfee81059175", size = 177542, upload-time = "2026-07-17T22:49:16.875Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ed/f1831681fce0e3242346e5458486003c5f124ed69e5e0b847fd029db4973/websockets-16.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f62863e8a00a6d33c3d6566ec0b89f23787b747ffe0c3bc71ec0e76b82c94b1", size = 187137, upload-time = "2026-07-17T22:49:18.323Z" }, + { url = "https://files.pythonhosted.org/packages/6f/79/4ff9dcc1bb46f6b4c536936dde1fd60f9b564f3304307274db97f4c9496d/websockets-16.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8087e82f842609734c9b5a1330464f8e94e346ba0e18c832c08bafa4b0d63c15", size = 188374, upload-time = "2026-07-17T22:49:19.65Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/5c49b6efb36cab733d23773f6de575e1dba65736ead17d5d2b2a1daef779/websockets-16.1.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2bb5d041a8307d2e18782e7ce777f6fdb1e8c2f5d09291484b18c294b789d9aa", size = 191155, upload-time = "2026-07-17T22:49:21.331Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f6/56ccceda3a4838d18f1d40821480da4775397e8b1eecf4031e20c50e2e90/websockets-16.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1db4de4a0e95673f7545d393c49eeb0c2f18ac1ef93073218c79d5cdb2ee75ab", size = 189011, upload-time = "2026-07-17T22:49:22.889Z" }, + { url = "https://files.pythonhosted.org/packages/86/d6/ad5286241a2bce1107e2798d3bfbd62cf79aee167bdb654f8cb1e9dbf949/websockets-16.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f17dbe07eb3ea7f99e4df9b7e0efefe80fbf30d37a8cc4d561a0aed310bc8847", size = 187766, upload-time = "2026-07-17T22:49:24.339Z" }, + { url = "https://files.pythonhosted.org/packages/bc/67/d65c970b7e347fdca69479beb7811c2060529956730a7a4e3ae7c66b0e31/websockets-16.1.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4b57693728576d84ede0a77987ab16881b783d2cd9f1dc180a8fbbc3f79c4428", size = 185173, upload-time = "2026-07-17T22:49:25.743Z" }, + { url = "https://files.pythonhosted.org/packages/1d/5b/14af3cd4ee69d8ea9baca58f3dc3cfb1ba78332a347fd478cb096549d60e/websockets-16.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2a636ff1e7a5c4edf71ef0e79adae7f25dba93b4fcbe3dc958733477ffeb0eaf", size = 187809, upload-time = "2026-07-17T22:49:27.147Z" }, + { url = "https://files.pythonhosted.org/packages/7b/11/be301710d70de97e3e7b3586e6d492c9c06d6a61bf1c2202c36cf0c75607/websockets-16.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d6bec75c290fe484a8ba4cacdf838501e17c06ecfbbf31eede81a9e431bd7751", size = 186412, upload-time = "2026-07-17T22:49:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/db/07/fe1435bf6fe738a3d3b54dbe0c18dabf12cba4d909ac8b58b539ce27c1f4/websockets-16.1.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:54509b8e92fee4453e152b7558ddef37ce9705a044922f2095a6105e3f80c96f", size = 188290, upload-time = "2026-07-17T22:49:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0a/81f394aff8efcbb01208c1ced77df0a3c7fcce584a88c7273663697946c2/websockets-16.1.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:f0aa4aad3b1b69ad3fd85a0fd0952ec64331c762bd77ec51cc814170873890b2", size = 185844, upload-time = "2026-07-17T22:49:31.447Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/dd485b995473f415510251fe9bd708f2d24458f439fce958daf8d66dc7c6/websockets-16.1.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:42290eb6db4ccaca7012656738214f8514082fb6fa40cdeb61bb9a471b52e383", size = 186823, upload-time = "2026-07-17T22:49:33.104Z" }, + { url = "https://files.pythonhosted.org/packages/9d/0b/f78de76ff446f1e66af12b43c48a35f31744de93cfdec2f4ea67d5d7bbf1/websockets-16.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:53260c8930da5771cec89439bff99c20c8cb03ddb9588b980697355a83cd4bd3", size = 187102, upload-time = "2026-07-17T22:49:34.616Z" }, + { url = "https://files.pythonhosted.org/packages/37/a1/4cf892007778eaf84ad162bfc98046e0ed89b63ac55949e3236626b2a23f/websockets-16.1.1-cp312-cp312-win32.whl", hash = "sha256:1d27fa8462ad6a1cb36206a3d0640b2333340def181fae11ed7f9adeaa5c0747", size = 179943, upload-time = "2026-07-17T22:49:36.213Z" }, + { url = "https://files.pythonhosted.org/packages/d9/de/6abe251d28c3a3f217096575400b27750b18e0b1d2fff3a2a239960fea07/websockets-16.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:b436f6ec4fc3a6b4237c84d3f83170ed2b40bb584222f0ac47a0c8a5921980c7", size = 180243, upload-time = "2026-07-17T22:49:37.626Z" }, + { url = "https://files.pythonhosted.org/packages/ce/fd/6ec6c6d2850aea25b1b2aa9901a016980bb87d01e89b3eb00470b1b5d471/websockets-16.1.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ab59169ace05dcb49a1d4118f0bde139557adf45091bd85747e36bf5de984dd1", size = 179587, upload-time = "2026-07-17T22:49:38.959Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d8/1d299d2dd34087db39831a34cc645ef8a6f89d78efada6983093513cd81c/websockets-16.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5e3b7d601f6f84156b08cc4a5e541c2b50ad7b36cfc302b657a12477c904a5df", size = 177272, upload-time = "2026-07-17T22:49:40.293Z" }, + { url = "https://files.pythonhosted.org/packages/3d/86/0a70d3ae2f0f2256bb41302d9804dbca65d4360281e7feb3e1f94102ac46/websockets-16.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cd2ca96a082a36964aca83e992f72abeb61b7306c1a6cba4c7d06a7b93750cac", size = 177530, upload-time = "2026-07-17T22:49:41.786Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c2/c676c69444d9db448b3f0a55a98dcc534affce0bce961d9d2f0b8499b10a/websockets-16.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f5d497865f05bb222cab7016c6034542e84e5f29f49c6fd3f4939cda7197b5b8", size = 187197, upload-time = "2026-07-17T22:49:43.658Z" }, + { url = "https://files.pythonhosted.org/packages/0b/13/88137fbaf726ebe29d62c1117fa11fa2bbb6209dc79d4ad738efbe36a2aa/websockets-16.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bae954c382e013d5ea5b190d2830526bfa45ad121c326da0049b8c769f185db6", size = 188433, upload-time = "2026-07-17T22:49:45.147Z" }, + { url = "https://files.pythonhosted.org/packages/01/6d/46c2f2ce6751cb26f39293e1ecbf8544cb01321397cd476c2756b98c216d/websockets-16.1.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e09f753a169951eb4f28c2c774f71069304f66e7277e0f5a2892423599cfa854", size = 189868, upload-time = "2026-07-17T22:49:46.581Z" }, + { url = "https://files.pythonhosted.org/packages/29/2b/170a9e8097636cfde4dc3c592b6e00b18a44a2f5407606d96ca542dd5838/websockets-16.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:024193f8551a2b0eafbdd160911012c4e6c228c28430c84433253299a9e42d6a", size = 189059, upload-time = "2026-07-17T22:49:47.972Z" }, + { url = "https://files.pythonhosted.org/packages/a7/48/f0d4ebc9ab4b473b8861b9e20fdb663d515d42f7befdf62cdb60fee7a1ec/websockets-16.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aabe464bfd13bd25f4821faf111da6fefdc389f870265a53105580e45b0a2e49", size = 187814, upload-time = "2026-07-17T22:49:49.344Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ba/39a41d3ae8e72696a9492581900611c5a91e2b07563b0bcd2523adea9854/websockets-16.1.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a28fcbc9b6baf54a2e23f8655f308e4ccc6afdd7266f8fe7954f320dcda0f785", size = 185229, upload-time = "2026-07-17T22:49:50.787Z" }, + { url = "https://files.pythonhosted.org/packages/3c/36/ac15b604f850d1907f0a85ed721cefe47cd45034b3620069b829746cccbe/websockets-16.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79eace538c6a97e96d0d03d4f9d314f9677f5ed85a8a984992ffd90b13cb8a56", size = 187874, upload-time = "2026-07-17T22:49:52.228Z" }, + { url = "https://files.pythonhosted.org/packages/a8/f3/3fbd5d71d59299c3770faa5884d4f45070236ca5a35ab3a61830812c409a/websockets-16.1.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:496af849a472b531f758dbd4d61338f5000538cb1a7b3d20d9d32a264517f509", size = 186469, upload-time = "2026-07-17T22:49:53.776Z" }, + { url = "https://files.pythonhosted.org/packages/b4/fc/dd90349bba58af2a53ef2ddd9c32716c81eb6d59a0687939fff561860878/websockets-16.1.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5283810d2646741a0d8da2aa733d6aefa0545809afccb2a5d105a26bc45125f1", size = 188347, upload-time = "2026-07-17T22:49:55.202Z" }, + { url = "https://files.pythonhosted.org/packages/4c/f3/f73ba86427682da59b78c11d77ba56d5b801c32e84afe79b274bbd6a9bb2/websockets-16.1.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4e3b680b1e0a27457e727a0d572fd81dffa87b6dbf8b228ab57da64f7d85aead", size = 185903, upload-time = "2026-07-17T22:49:56.75Z" }, + { url = "https://files.pythonhosted.org/packages/34/7c/f95eb20e80104173b3a0a092291f89ea4047ef6e608e0a57ca06eb14eecb/websockets-16.1.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:69159730a823dde3ea8d08783e8d47ef135a6d7e8d44eb127e32b321c9db8e3e", size = 186855, upload-time = "2026-07-17T22:49:58.467Z" }, + { url = "https://files.pythonhosted.org/packages/b0/35/dd875b3e050ff232d60fa377707f890e369f74d134f1be32e8f68879747c/websockets-16.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ed5bb271084b46530ee2ddc0410537a9961152c5ccba2fc98c5276d992ccba87", size = 187140, upload-time = "2026-07-17T22:50:00.016Z" }, + { url = "https://files.pythonhosted.org/packages/e8/dc/5cbfcb41824502f6af93b8f3943a4d06c67c23c7d2e31eb18748c4a5b2a7/websockets-16.1.1-cp313-cp313-win32.whl", hash = "sha256:cfb70b4eb56cac4da0a83588f3ad50d46beb0690391082f3d4e2d488c70b68ea", size = 179928, upload-time = "2026-07-17T22:50:01.685Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c1/71e5deb5b7f8f226997ab64908c184ac3105c0155ce2d486f318e5dd08a8/websockets-16.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:d9531d9cbeac99af6f038fb1bc351403531f7d634a2c2e10e2f7c854c6ed5b68", size = 180242, upload-time = "2026-07-17T22:50:03.117Z" }, + { url = "https://files.pythonhosted.org/packages/73/a2/ba78a164eeea4620df4a4df4bd2ed6017438c4655cc0f36f2c0bc0432355/websockets-16.1.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:443aefe96b7fdb132e2a70806cca1f2af49bb3f28e47abcd7c2e9dcf4d8fa1b8", size = 179635, upload-time = "2026-07-17T22:50:05.001Z" }, + { url = "https://files.pythonhosted.org/packages/b9/08/d26d7a7628cd4ac34cbbdb63ac80914ca842ed8e42938c40a53567806df3/websockets-16.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6456ff333092d509127d75a638cb411afae8ff17f092635015d1902efec8a293", size = 177320, upload-time = "2026-07-17T22:50:06.427Z" }, + { url = "https://files.pythonhosted.org/packages/0f/45/ebec83e6269536aa5932533c67b0af5c781f3e73fdbcd68672dcf43f4f44/websockets-16.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fce6c48559c86d1ac3632ccb1bebc7d5442fbe79bd9bb0e40379ee54be2a4051", size = 177544, upload-time = "2026-07-17T22:50:07.834Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d5/abc614d2297f6c1c3e01e61260364457a47c25cc1cf6a879038902bc6aa8/websockets-16.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:92b820d345f7a3fc7b8163949ee92df910f290c3fc517b3d5301c78065adafe1", size = 187270, upload-time = "2026-07-17T22:50:09.275Z" }, + { url = "https://files.pythonhosted.org/packages/52/71/4c99af3b87dff1b2927981f6876607d4acb45338c665242168d3982f7758/websockets-16.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a606d9c24035242a3e256e9d5b77ed9cd6bccfcb7cf993e5ca3c0f6f68fb6a7", size = 188509, upload-time = "2026-07-17T22:50:10.722Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b4/5c8ca14b0df7eb84ed0524165c5359150210140817a3312aee57bf62a1cf/websockets-16.1.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:414e596c75f74e0994084694189d7dc9229fb278e33064d6784b73ffbba3ca31", size = 189882, upload-time = "2026-07-17T22:50:12.293Z" }, + { url = "https://files.pythonhosted.org/packages/25/c1/bedfba9e70557129cb8083748d167bdcc01483dedf0f0df143676df05cbe/websockets-16.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:536676848fc5961aca9d20389951f59169508f765637a172403dc5434d722fa0", size = 189114, upload-time = "2026-07-17T22:50:13.789Z" }, + { url = "https://files.pythonhosted.org/packages/df/09/aa835b2787835aebd839114be5de51b797cb480b63ba42b26d34dfe147cb/websockets-16.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:97fd3a0e8b53efa41970ac1dff3d8cf0d2884cadeb4caaf95db7ad1526926ee3", size = 187861, upload-time = "2026-07-17T22:50:15.179Z" }, + { url = "https://files.pythonhosted.org/packages/20/26/f6408330694dbc9830857d9d23bc14ac4f6875127a480cfdda8d5ca21198/websockets-16.1.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7b1b19636af86a3c7995d4d028dbe376f39b4bf31541146f9c123582a6c94562", size = 185286, upload-time = "2026-07-17T22:50:16.741Z" }, + { url = "https://files.pythonhosted.org/packages/17/9a/e0675e70dd8a80762cf35bb18799d3f290a4890ffe6439bc51d222796083/websockets-16.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:41c8e77f17294c0ac18008a7309b99b34ee72247ef10b6dff4c3f8b5ac29896b", size = 187935, upload-time = "2026-07-17T22:50:18.213Z" }, + { url = "https://files.pythonhosted.org/packages/33/c1/3234cfb86afde01b81e9bddcc6e534c440975d60a13991259e833069ab3e/websockets-16.1.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9f63bcef7f4b02b06b35fc01c93b96c43b5e88e1e8868676caacf493d5a31f3a", size = 186444, upload-time = "2026-07-17T22:50:19.67Z" }, + { url = "https://files.pythonhosted.org/packages/89/87/9c15206e1d778923d8daa9657de07aa62ea815e13448319c98458c37b281/websockets-16.1.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dab9eb87869da2d6ed3af3f3adf28414baae6ec9d4df355ffc18889132f3436c", size = 188409, upload-time = "2026-07-17T22:50:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/cf5de5c67676de2d3eef8b2a518f168f6796595447a5b7161ba0d012915c/websockets-16.1.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:43e3a9fdd7cbf7ba6040c31fae0faf84ca1474fef777c4e37912f1540f854499", size = 185958, upload-time = "2026-07-17T22:50:22.719Z" }, + { url = "https://files.pythonhosted.org/packages/62/c0/731b6ddede2e4136912ec4cff2cffbda35af73546be4762c3d7bd3bd79af/websockets-16.1.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:056ae37939ed7e9974f364f5864e76e49182622d8f9751ac1903c0d09b013985", size = 186911, upload-time = "2026-07-17T22:50:24.108Z" }, + { url = "https://files.pythonhosted.org/packages/8c/7f/39c634472c4469a24a7c09cecddffb08fac6d0e74f73881a94ee8a40a196/websockets-16.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a0eadbbf2c30f01efa58e1f110eb6fa293261f6b0b1aa38f7f48707107690af9", size = 187204, upload-time = "2026-07-17T22:50:25.548Z" }, + { url = "https://files.pythonhosted.org/packages/26/89/9667c256c256dafcc62d21328ce7a40067da857969b68ee9af375b0aaf72/websockets-16.1.1-cp314-cp314-win32.whl", hash = "sha256:195c978b065fa40910582464f99d6b15c8b314c68e0546549a55ed83f4735328", size = 179603, upload-time = "2026-07-17T22:50:27.086Z" }, + { url = "https://files.pythonhosted.org/packages/bd/dd/1c099d6c0fc5deb6b46ccdbb6981fdb4b12c917869cb3952408409dc18db/websockets-16.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:4e8d01cc3bcae7bbf8167f944aeafefed590fae5693552bba9794a9df68371cc", size = 179948, upload-time = "2026-07-17T22:50:28.521Z" }, + { url = "https://files.pythonhosted.org/packages/35/25/9956b2d5e0529d5d23924f21bba1440d4c5c88a562e4f08550871ffa97a7/websockets-16.1.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0ffd3031ea8bda8d61762e84220186105ba3b748b3c8da2ae4f7816fac03e573", size = 179963, upload-time = "2026-07-17T22:50:29.982Z" }, + { url = "https://files.pythonhosted.org/packages/17/06/55ffc976c488b6aee9ea05761ff7c4e88e7c1fd82818c8ca7b556ad2f90c/websockets-16.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:84a2cef8deffbd9ab8ee0ea546a2a6a7030c28f44e6cdd4547dbfeb489eb8999", size = 177497, upload-time = "2026-07-17T22:50:31.396Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/f7dac2e980bacc92bdc26cebae4ae4d50cae5380732c50980598fc0bbae4/websockets-16.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3df13f73af9b3b38ab1195eb299ecb67a4330c911c97ae04043ff74085728abe", size = 177698, upload-time = "2026-07-17T22:50:32.829Z" }, + { url = "https://files.pythonhosted.org/packages/b2/39/26762f734113e22da2b942c3aca85798e0c0405d64c256549540ff31e5a1/websockets-16.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:23253dd5bcae3f9aaee0a1d30967a8dbd52e5d3cff93a2e5b84df57b77d4750d", size = 187561, upload-time = "2026-07-17T22:50:34.24Z" }, + { url = "https://files.pythonhosted.org/packages/11/94/c3f330851806b9b02138b774d593478323e73c99238681b4b93efe64e02d/websockets-16.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c1c5705e314449e3308872fe084b8571ce078ee4fc55a98a769bdefe5917392", size = 188732, upload-time = "2026-07-17T22:50:36.088Z" }, + { url = "https://files.pythonhosted.org/packages/d1/f2/eb2c450f052de334ae33cf200ece6e87b0e14d186807074e4eb1cd2cdea2/websockets-16.1.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69e52d175a0a7d1e13b4b67ad41c560b7d98e8c6f6126eb0bda496c784faf8c7", size = 190872, upload-time = "2026-07-17T22:50:38.008Z" }, + { url = "https://files.pythonhosted.org/packages/70/31/2ac8cecf3a74f7fed9132129fc3d90b3998a1554570c11a69b2a8c20332d/websockets-16.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1f79c89b5eb034d1722938a891916582f8f7f503f58ca22518a63c3f2cd18499", size = 189305, upload-time = "2026-07-17T22:50:39.53Z" }, + { url = "https://files.pythonhosted.org/packages/6a/cf/8ab19650d3c0d4562c92e70ab47c257c4aa5c6a713ed87fe63766b31fefc/websockets-16.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:39f2a024af5c345ffe8fcf1ee18c049c024c94df393bb09b044a6917c77bde43", size = 188033, upload-time = "2026-07-17T22:50:40.912Z" }, + { url = "https://files.pythonhosted.org/packages/66/d7/a49a38a6127a4acb134fb1912b215d900cc657605cff32445bf519f3acc4/websockets-16.1.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:952303a7318d4cbe1011400839bb2051c9f84fa0a35923267f5daba34b15d458", size = 185748, upload-time = "2026-07-17T22:50:42.559Z" }, + { url = "https://files.pythonhosted.org/packages/95/3e/ad1fa40388c7f2e0bb2c7930d0090b6c5498594bd1cdaec18864df3d9e97/websockets-16.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:249116b4a76063d930a46391ad56e135c286e4562a18309029fc2c73f4ed4c62", size = 188285, upload-time = "2026-07-17T22:50:43.974Z" }, + { url = "https://files.pythonhosted.org/packages/35/b8/d5db28ca264b9104f82196f92dc8843e35fd391f763d42e4ad358f5bc97e/websockets-16.1.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:61922544a0587a13fd3f53e4c0e5e606510c7b0d9d22c8444e5fae22a06b38cb", size = 186777, upload-time = "2026-07-17T22:50:45.474Z" }, + { url = "https://files.pythonhosted.org/packages/42/9c/726cb39d0cc43ae848dce4aa2acb04eecc6738b1264ec6d700bf6bcfb9f8/websockets-16.1.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:46dcaa042cd1de6c59e7d9269fa63ff7572b6df40510600b678f0826b3c7af51", size = 188682, upload-time = "2026-07-17T22:50:46.973Z" }, + { url = "https://files.pythonhosted.org/packages/be/c7/1168704de8c2dd483edabe4a22cbe4465dd8be8dd95561d214f9fe092871/websockets-16.1.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:38565aca3e01ea8734e578fb2118dade0ecb0250533f29e22b8d1a7a196cf4d0", size = 186377, upload-time = "2026-07-17T22:50:48.413Z" }, + { url = "https://files.pythonhosted.org/packages/ca/40/f9ff2d630ffce4e7dfea0b2288e1caf9ebbf9ff8a9ec9396136ce8b94935/websockets-16.1.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:42f599f4d48c7e1a3338fdaac3acd075be3b3cf02d4b274f3bf2767aedd3d217", size = 187148, upload-time = "2026-07-17T22:50:49.845Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/e177c8299f78d7cbe2d14df228643c10c70c0e86e108e092056bbcc16e46/websockets-16.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dcc04fedf83effaeb9cce98abc9469bb1b42ef85f03e01c8c1f4438ef7555737", size = 187578, upload-time = "2026-07-17T22:50:51.619Z" }, + { url = "https://files.pythonhosted.org/packages/49/b2/b6987faf330f5af5c787a2610124c2e8403d51724f9001ec4fff6311fe7a/websockets-16.1.1-cp314-cp314t-win32.whl", hash = "sha256:8483c2096363120eea8b07c06ae7304d520f686665fffd4811fad423930a65d7", size = 179729, upload-time = "2026-07-17T22:50:53.269Z" }, + { url = "https://files.pythonhosted.org/packages/a2/6e/fbac6ed878dd362fbad7d415fa4f84d38e3e33fed8cde45c64e783acf826/websockets-16.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bcce07e23e5769375158f5efdcdafa8d5cd014b93c6683865b840ed65b96f231", size = 180072, upload-time = "2026-07-17T22:50:54.969Z" }, + { url = "https://files.pythonhosted.org/packages/be/4d/2d0d67834092e354d2b0498f014a41249a89556bc406cf86f3e1557bb463/websockets-16.1.1-py3-none-any.whl", hash = "sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3", size = 173814, upload-time = "2026-07-17T22:51:04.184Z" }, +] diff --git a/launch/README.md b/launch/README.md new file mode 100644 index 0000000..e7f5158 --- /dev/null +++ b/launch/README.md @@ -0,0 +1,25 @@ +# Gloss launch assets + +The launch page and film are static, repository-owned, and derived from committed evidence. + +## Evidence + +`site/evidence/preview-v1.json` is the single launch evidence bundle. It records the exact generated mutation reports and SHA-256 hashes used for every homepage and film count. + +Verify the evidence, local links, caveats, and media metadata: + +```bash +node launch/verify-launch.mjs +``` + +## Film + +Rebuild the silent 1080×1080, 30 fps, 21-second MP4 and poster: + +```bash +node launch/render-video.mjs +``` + +The renderer uses Node.js standard libraries, `rsvg-convert`, and `ffmpeg`. It creates temporary frames in the operating system temporary directory and removes them after encoding. + +The film deliberately reports harness composition and mutation-operator evidence. It does not show model rankings because no verified model-result cohort exists yet. diff --git a/launch/launch-post.md b/launch/launch-post.md new file mode 100644 index 0000000..c9794e6 --- /dev/null +++ b/launch/launch-post.md @@ -0,0 +1,32 @@ +# Gloss launch post + +## Primary post + +A screenshot is not a PowerPoint. + +Gloss is an open benchmark for generated decks that need to look right **and** be built right: native shapes, charts, tables, layouts, text, assets, and OOXML relationships. + +The technical preview has 280 candidate checks. Its generated operator suite passes 280/280 positive controls and detects 280/280 single-fault mutations. It is not an official model leaderboard yet — independent evidence and the release freeze are still open. + +That work is public. Break a case, tighten an assertion, or challenge the evidence: + +https://gloss.tools +https://github.com/aronchick/gloss + +## Short version + +A screenshot is not a PowerPoint. + +Gloss checks whether generated decks look right and are built right — all the way down to native OOXML. + +280 candidate checks. 280/280 generated mutations detected. No invented model leaderboard. The evidence and unfinished release gates are public. + +Build it with us: https://gloss.tools + +## Video alt text + +Square, silent launch film on a clean light background. It introduces Gloss, then animates two bars showing 172 candidate checks inside the PowerPoint file and 108 on the rendered canvas. A dark title card reads “The artifact twist” and explains that 61% of candidate checks live inside the file. A second chart ranks the inside-file methods: object structure 101, layouts and masters 25, package safety 22, text semantics 20, and asset hashes 4. The end card reads “Gloss — Generative Layout & OOXML Scoring System,” “280 / 280 generated single-fault mutations detected,” and “gloss.tools.” The film labels the release as an open technical preview. + +## Posting note + +Attach `site/media/gloss-launch.mp4`. If a platform strips video metadata or recompresses the file, keep the public post copy unchanged; the source evidence remains `site/evidence/preview-v1.json`. diff --git a/launch/render-video.mjs b/launch/render-video.mjs new file mode 100644 index 0000000..915b95e --- /dev/null +++ b/launch/render-video.mjs @@ -0,0 +1,266 @@ +#!/usr/bin/env node + +import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const launchDir = dirname(fileURLToPath(import.meta.url)); +const root = resolve(launchDir, ".."); +const evidencePath = join(root, "site/evidence/preview-v1.json"); +const outputPath = join(root, "site/media/gloss-launch.mp4"); +const posterPath = join(root, "site/media/gloss-launch-poster.png"); +const evidence = JSON.parse(readFileSync(evidencePath, "utf8")); + +const width = 1080; +const height = 1080; +const fps = 30; +const duration = 21; +const frameCount = fps * duration; +const colors = { + canvas: "#f4f6fa", + paper: "#ffffff", + ink: "#171a22", + muted: "#68717f", + rule: "#c9ced8", + orange: "#d35230", + orangeSoft: "#f7ded5", + blue: "#2859d6", + blueSoft: "#dfe8ff", + proof: "#b7f36b", +}; + +function commandExists(command) { + return spawnSync("sh", ["-c", `command -v ${command}`], { stdio: "ignore" }).status === 0; +} + +function requireCommand(command) { + if (!commandExists(command)) { + throw new Error(`${command} is required to render the launch video`); + } +} + +function clamp(value, min = 0, max = 1) { + return Math.min(max, Math.max(min, value)); +} + +function ease(value) { + const t = clamp(value); + return 1 - (1 - t) ** 3; +} + +function fadeInOut(t, start, end, edge = 0.4) { + return clamp((t - start) / edge) * clamp((end - t) / edge); +} + +function escapeXml(value) { + return String(value) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} + +function svgText(text, x, y, options = {}) { + const { + size = 48, + weight = 700, + fill = colors.ink, + anchor = "start", + family = "Aptos Display, Arial Narrow, Segoe UI, sans-serif", + spacing = 0, + opacity = 1, + } = options; + return `${escapeXml(text)}`; +} + +function mono(text, x, y, options = {}) { + return svgText(text, x, y, { + family: "SFMono-Regular, Consolas, Liberation Mono, monospace", + size: 22, + weight: 700, + spacing: 1.5, + ...options, + }); +} + +function baseSvg(body, background = colors.canvas) { + return ` + + ${body} + `; +} + +function frameIntro(t) { + const p = ease(t / 1.5); + const opacity = fadeInOut(t, 0, 2, 0.35); + const offset = 40 * (1 - p); + return baseSvg(` + + ${mono("OPEN POWERPOINT BENCHMARK", 72, 112, { fill: colors.orange })} + ${svgText("Gloss", 72, 480, { size: 230, weight: 780 })} + + ${svgText("Same file.", 76, 655, { size: 78, weight: 720 })} + ${svgText("Two truths.", 76, 742, { size: 78, weight: 720, fill: colors.blue })} + ${mono("LOOKS RIGHT ↔ BUILT RIGHT", 76, 928, { fill: colors.muted })} + + `); +} + +function frameTwoLayers(t) { + const local = t - 2; + const opacity = fadeInOut(t, 2, 9.2, 0.35); + const total = evidence.candidate_checks.total; + const visual = evidence.candidate_checks.visual_render; + const inside = evidence.candidate_checks.inside_file; + const progress = ease(local / 4.8); + const rows = [ + { label: "INSIDE THE FILE", count: inside, color: colors.blue, y: 478 }, + { label: "ON THE CANVAS", count: visual, color: colors.orange, y: 682 }, + ]; + const rowMarkup = rows.map((row, index) => { + const stagger = ease((local - index * 0.32) / 3.4); + const barWidth = (row.count / inside) * 760 * stagger; + const count = Math.round(row.count * progress); + return ` + ${mono(row.label, 78, row.y - 28, { fill: colors.muted, size: 19 })} + + + ${svgText(String(count), 952, row.y + 67, { size: 62, weight: 760, anchor: "end" })} + `; + }).join(""); + return baseSvg(` + + ${mono("GLOSS / CANDIDATE HARNESS", 78, 90, { fill: colors.orange })} + ${svgText(`${total} ways to ask`, 78, 230, { size: 100, weight: 760 })} + ${svgText("if a deck is real.", 78, 332, { size: 100, weight: 760 })} + ${rowMarkup} + ${mono("CANDIDATE CHECK COUNTS · NOT MODEL SCORES", 78, 966, { fill: colors.muted, size: 18 })} + + `); +} + +function frameTwist(t) { + const local = t - 9.2; + const opacity = fadeInOut(t, 9.2, 11, 0.2); + const p = ease(local / 1.2); + const percent = Math.round(evidence.candidate_checks.inside_file_percent * p); + return baseSvg(` + + + + ${mono("THE ARTIFACT TWIST", 92, 130, { fill: colors.proof })} + ${svgText(`${percent}%`, 540, 550, { size: 310, weight: 790, fill: colors.paper, anchor: "middle" })} + ${svgText("of candidate checks", 540, 680, { size: 70, weight: 700, fill: colors.paper, anchor: "middle" })} + ${svgText("live inside the file.", 540, 760, { size: 70, weight: 700, fill: colors.blueSoft, anchor: "middle" })} + ${mono("LOOKING RIGHT ISN’T BEING EDITABLE", 540, 927, { fill: "#aab2c0", anchor: "middle", size: 19 })} + + `, colors.ink); +} + +function frameMethods(t) { + const local = t - 11; + const opacity = fadeInOut(t, 11, 18.2, 0.3); + const methods = evidence.verification_methods.filter((method) => method.id !== "visual_ssim"); + const max = Math.max(...methods.map((method) => method.count)); + const rows = methods.map((method, index) => { + const y = 390 + index * 120; + const p = ease((local - index * 0.2) / 3.5); + const barWidth = (method.count / max) * 670 * p; + return ` + ${mono(`${String(index + 1).padStart(2, "0")} ${method.public_label.toUpperCase()}`, 76, y - 18, { fill: colors.muted, size: 18 })} + + + ${svgText(String(Math.round(method.count * p)), 944, y + 48, { size: 48, weight: 760, anchor: "end" })} + `; + }).join(""); + return baseSvg(` + + ${mono("BUILT RIGHT / INSIDE-FILE CHECKS", 76, 82, { fill: colors.blue })} + ${svgText("What the screenshot", 76, 202, { size: 88, weight: 760 })} + ${svgText("cannot tell you.", 76, 292, { size: 88, weight: 760 })} + ${rows} + ${mono(`${evidence.candidate_checks.inside_file} CANDIDATE CHECKS · ${evidence.operator_evidence.operators} MUTATION OPERATORS`, 76, 1020, { fill: colors.muted, size: 17 })} + + `); +} + +function frameEnd(t) { + const local = t - 18.2; + const p = ease(local / 1.1); + const opacity = clamp(local / 0.25); + return baseSvg(` + + ${mono("OPEN TECHNICAL PREVIEW", 74, 92, { fill: colors.proof })} + ${svgText("Gloss", 72, 388, { size: 230, weight: 790, fill: colors.paper })} + + ${svgText("Generative Layout &", 76, 545, { size: 50, weight: 690, fill: "#cdd3df" })} + ${svgText("OOXML Scoring System", 76, 607, { size: 50, weight: 690, fill: "#cdd3df" })} + + ${svgText(`${evidence.operator_evidence.single_fault_mutations_detected} / ${evidence.operator_evidence.single_fault_mutations}`, 76, 795, { size: 78, weight: 780, fill: colors.proof })} + ${mono("GENERATED SINGLE-FAULT MUTATIONS DETECTED", 76, 837, { fill: "#aeb6c4", size: 17 })} + ${svgText("gloss.tools", 76, 982, { size: 72, weight: 760, fill: colors.paper })} + ${mono("BUILD IT WITH US ON GITHUB ↗", 1004, 982, { fill: colors.orange, anchor: "end", size: 17 })} + + `, colors.ink); +} + +function renderFrame(time) { + if (time < 2) return frameIntro(time); + if (time < 9.2) return frameTwoLayers(time); + if (time < 11) return frameTwist(time); + if (time < 18.2) return frameMethods(time); + return frameEnd(time); +} + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { encoding: "utf8", ...options }); + if (result.status !== 0) { + throw new Error(`${command} failed\n${result.stderr || result.stdout}`); + } + return result; +} + +requireCommand("rsvg-convert"); +requireCommand("ffmpeg"); + +mkdirSync(dirname(outputPath), { recursive: true }); +const frameDir = mkdtempSync(join(tmpdir(), "gloss-launch-")); + +try { + for (let frame = 0; frame < frameCount; frame += 1) { + const time = frame / fps; + const framePath = join(frameDir, `frame-${String(frame).padStart(4, "0")}.png`); + run("rsvg-convert", ["--width", String(width), "--height", String(height), "--output", framePath], { + input: renderFrame(time), + }); + if (frame % 90 === 0) process.stdout.write(`Rendered ${frame}/${frameCount} frames\n`); + } + + const posterFrame = join(frameDir, `frame-${String(frameCount - 1).padStart(4, "0")}.png`); + copyFileSync(posterFrame, posterPath); + + run("ffmpeg", [ + "-y", + "-loglevel", "error", + "-framerate", String(fps), + "-i", join(frameDir, "frame-%04d.png"), + "-t", String(duration), + "-c:v", "libx264", + "-preset", "slow", + "-crf", "18", + "-pix_fmt", "yuv420p", + "-movflags", "+faststart", + "-metadata", `title=Gloss — ${evidence.product_retronym}`, + "-metadata", `comment=Rendered from ${evidence.evidence_id}`, + "-an", + outputPath, + ]); + + if (!existsSync(outputPath)) throw new Error("Video renderer did not create its output"); + process.stdout.write(`Created ${outputPath}\nCreated ${posterPath}\n`); +} finally { + rmSync(frameDir, { recursive: true, force: true }); +} diff --git a/launch/verify-launch.mjs b/launch/verify-launch.mjs new file mode 100644 index 0000000..40edc11 --- /dev/null +++ b/launch/verify-launch.mjs @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +import { createHash } from "node:crypto"; +import { existsSync, readFileSync, statSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const launchDir = dirname(fileURLToPath(import.meta.url)); +const root = resolve(launchDir, ".."); +const site = join(root, "site"); +const evidencePath = join(site, "evidence/preview-v1.json"); +const evidence = JSON.parse(readFileSync(evidencePath, "utf8")); +const reportPath = join(root, "acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json"); +const indexPath = join(root, "acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json"); +const expectationsPath = join(root, "acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json"); +const requirementsPath = join(root, "acidslide-v1/benchmark/requirements/prompt-requirements.json"); +const report = JSON.parse(readFileSync(reportPath, "utf8")); +const index = JSON.parse(readFileSync(indexPath, "utf8")); +const requirements = JSON.parse(readFileSync(requirementsPath, "utf8")); +const html = readFileSync(join(site, "index.html"), "utf8"); + +function assert(condition, message) { + if (!condition) throw new Error(message); +} + +function sha256(path) { + return createHash("sha256").update(readFileSync(path)).digest("hex"); +} + +const methodCounts = Object.fromEntries( + Object.entries(index.entries.reduce((counts, entry) => { + counts[entry.verification_method] = (counts[entry.verification_method] || 0) + 1; + return counts; + }, {})), +); +const positivePassed = report.results.filter((result) => result.positive_passed).length; +const mutantsDetected = report.results.filter((result) => result.mutant_killed).length; +const visual = methodCounts.visual_ssim; +const insideFile = index.entries.length - visual; +const requirementCounts = requirements.requirements.reduce((counts, requirement) => { + counts[requirement.scope] = (counts[requirement.scope] || 0) + 1; + return counts; +}, {}); + +assert(evidence.status === "technical_preview", "Launch evidence must remain labeled technical_preview"); +assert(evidence.operator_evidence.release_evidence_claimed === 0, "Preview must not claim release evidence"); +assert(evidence.candidate_checks.total === index.entries.length, "Candidate-check count drifted from fixture index"); +assert(evidence.candidate_checks.visual_render === visual, "Visual-check count drifted from fixture index"); +assert(evidence.candidate_checks.inside_file === insideFile, "Inside-file count drifted from fixture index"); +assert(evidence.prompt_requirements.total === requirements.requirements.length, "Prompt-requirement total drifted from oracle"); +assert(evidence.prompt_requirements.deck === requirementCounts.deck, "Deck requirement count drifted from oracle"); +assert(evidence.prompt_requirements.slide === requirementCounts.slide, "Slide requirement count drifted from oracle"); +assert(evidence.operator_evidence.positive_controls_passed === positivePassed, "Positive-control count drifted from execution report"); +assert(evidence.operator_evidence.single_fault_mutations_detected === mutantsDetected, "Mutation count drifted from execution report"); + +for (const method of evidence.verification_methods) { + assert(method.count === methodCounts[method.id], `Verification method ${method.id} drifted from fixture index`); + const htmlLabel = method.public_label.replaceAll("&", "&"); + assert(html.includes(`${htmlLabel}`) && html.includes(`${method.count}`), `Homepage method count is missing for ${method.id}`); +} + +const sourcePaths = new Map([ + ["acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json", reportPath], + ["acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json", indexPath], + ["acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json", expectationsPath], + ["acidslide-v1/benchmark/requirements/prompt-requirements.json", requirementsPath], +]); +for (const source of evidence.sources) { + const sourcePath = sourcePaths.get(source.path); + assert(sourcePath, `Unknown evidence source ${source.path}`); + assert(sha256(sourcePath) === source.sha256, `SHA-256 drifted for ${source.path}`); +} + +const requiredCopy = [ + "A screenshot is not a", + "Open technical preview", + "0 official model results", + "The repository is the product", + "Working harness. Unfrozen benchmark.", +]; +for (const copy of requiredCopy) assert(html.includes(copy), `Homepage is missing required copy: ${copy}`); +assert(!/official leaderboard[^<]{0,80}(live|launched|ready)/i.test(html), "Homepage overclaims official leaderboard readiness"); +assert(html.includes("https://github.com/aronchick/gloss"), "Homepage must lead to GitHub"); + +const localAssetPattern = /(?:href|src)="\/(?!\/)([^"?#]*)/g; +for (const match of html.matchAll(localAssetPattern)) { + if (!match[1]) continue; + const assetPath = join(site, match[1]); + assert(existsSync(assetPath), `Homepage references missing local asset /${match[1]}`); +} + +const videoPath = join(site, "media/gloss-launch.mp4"); +const posterPath = join(site, "media/gloss-launch-poster.png"); +assert(statSync(videoPath).size > 100_000, "Launch video is missing or unexpectedly small"); +assert(statSync(posterPath).size > 20_000, "Launch poster is missing or unexpectedly small"); + +const probe = spawnSync("ffprobe", [ + "-v", "error", + "-show_entries", "stream=codec_type,width,height,avg_frame_rate:format=duration", + "-of", "json", + videoPath, +], { encoding: "utf8" }); +assert(probe.status === 0, `ffprobe is required to verify launch media: ${probe.stderr}`); +const metadata = JSON.parse(probe.stdout); +const video = metadata.streams.find((stream) => stream.codec_type === "video"); +const audio = metadata.streams.find((stream) => stream.codec_type === "audio"); +assert(video?.width === 1080 && video?.height === 1080, "Launch video must be 1080x1080"); +assert(video?.avg_frame_rate === "30/1", "Launch video must be 30 fps"); +assert(Math.abs(Number(metadata.format.duration) - 21) < 0.05, "Launch video must be 21 seconds"); +assert(!audio, "Launch video must be silent and contain no audio stream"); + +process.stdout.write(`Launch verification: PASS\n- evidence: ${evidence.evidence_id}\n- candidate checks: ${index.entries.length}\n- positive controls: ${positivePassed}/${report.results.length}\n- mutants detected: ${mutantsDetected}/${report.results.length}\n- site assets: present\n- video: 1080x1080, 30 fps, 21 seconds, silent\n`); diff --git a/site/evidence/preview-v1.json b/site/evidence/preview-v1.json new file mode 100644 index 0000000..c537248 --- /dev/null +++ b/site/evidence/preview-v1.json @@ -0,0 +1,112 @@ +{ + "schema_version": "1.0", + "evidence_id": "gloss-technical-preview-2026-07-22", + "product_name": "Gloss", + "product_retronym": "Generative Layout & OOXML Scoring System", + "protocol_id": "acidslide-v1", + "status": "technical_preview", + "status_label": "Technical preview — not an official leaderboard", + "claim": "The public candidate harness can execute 280 positive controls and detect 280 generated single-fault mutations. Independent assertion evidence and release approval remain incomplete.", + "candidate_checks": { + "total": 280, + "schema_valid": 280, + "visual_render": 108, + "inside_file": 172, + "inside_file_percent": 61, + "derivation": "inside_file = total candidate checks minus visual_ssim checks" + }, + "prompt_requirements": { + "total": 381, + "deck": 67, + "slide": 314, + "freeze_status": "candidate" + }, + "verification_methods": [ + { + "id": "object_compare", + "public_label": "Object structure", + "count": 101 + }, + { + "id": "layout_check", + "public_label": "Layouts & masters", + "count": 25 + }, + { + "id": "anti_cheat", + "public_label": "Package safety", + "count": 22 + }, + { + "id": "text_match", + "public_label": "Text semantics", + "count": 20 + }, + { + "id": "hash_match", + "public_label": "Asset hashes", + "count": 4 + }, + { + "id": "visual_ssim", + "public_label": "Rendered pixels", + "count": 108 + } + ], + "operator_evidence": { + "operators": 19, + "positive_controls": 280, + "positive_controls_passed": 280, + "single_fault_mutations": 280, + "single_fault_mutations_detected": 280, + "release_evidence_claimed": 0, + "scope": "Generated operator behavior only; not independent assertion provenance, review, or release evidence." + }, + "release_gates": { + "prompt_convergence_complete": 0, + "prompt_convergence_total": 20, + "assertion_evidence_complete": 0, + "assertion_evidence_total": 280, + "candidate_assertions_frozen": 0, + "candidate_assertions_total": 280, + "release_mode_passes": false + }, + "artifact_xray": { + "canvas_layer": { + "label": "Looks right", + "checks": 108, + "examples": [ + "full-slide render similarity", + "focal-region fidelity", + "cross-slide visual consistency" + ] + }, + "package_layer": { + "label": "Built right", + "checks": 172, + "examples": [ + "native charts, tables, and shapes", + "slide layouts, masters, and relationships", + "text semantics, asset hashes, and package safety" + ] + } + }, + "sources": [ + { + "path": "acidslide-v1/benchmark/fixtures/mutations/execution-report-v1.json", + "sha256": "9e53e25f7f18c9db8043c7dac096aa1b937d75876865a990140874b8750e074a" + }, + { + "path": "acidslide-v1/benchmark/fixtures/mutations/fixture-index-v1.json", + "sha256": "eb495d31e25596e5eab170e3ab1742110516f90fe3619d5a2b68ab041606b672" + }, + { + "path": "acidslide-v1/benchmark/fixtures/mutations/mutation-expectations-v1.json", + "sha256": "e829ef3bc0d9b017559258817de35562095b2a07d47dc41f4830dea5f0cd3f75" + }, + { + "path": "acidslide-v1/benchmark/requirements/prompt-requirements.json", + "sha256": "1f21fab0b81052e67e9eb60d29fe22ab2c9af9c90653bcae4c9f368ba31f7f88" + } + ] +} diff --git a/site/favicon.svg b/site/favicon.svg new file mode 100644 index 0000000..0e63d8e --- /dev/null +++ b/site/favicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..835ab36 --- /dev/null +++ b/site/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + Gloss — a screenshot is not a PowerPoint + + + + + + + + +
    +
    +
    +

    Open technical preview

    +

    A screenshot is not a PowerPoint.

    +

    Gloss measures whether generated decks look right and are built right — native shapes, charts, tables, layouts, text, and relationships included.

    + +

    Generative Layout & OOXML Scoring System · Apache-2.0

    +
    + +
    +
    +
    + + +
    + submission.pptx +
    +
    +
    +
    +
    Q3 / SYSTEMS
    +
    The artifact
    is the product.
    +
    +
    +
    Rendered pixels
    +
    +

    108 visual checks inspect what reaches the canvas.

    +
    + +
    +
    Gloss artifact X-raycanvas ↔ package
    +
    +
    + +
    + + Evidence bundle + Public JSON + Open the receipts ↗ + +
    + Candidate checks + 280 + 108 visual · 172 inside-file +
    +
    + Positive controls + 280/280 + passed +
    +
    + Single-fault mutations + 280/280 + detected +
    +
    + Release state + Preview + 0 official model results +
    +
    + +
    +
    +

    The 21-second version

    +

    The benchmark begins where the screenshot ends.

    +

    The film is rendered from the same committed JSON bundle as this page. These are harness counts, not model scores.

    +
    +
    + +
    00:211080 × 1080silentview renderer ↗
    +
    +
    + +
    +
    +

    One file. Two truths.

    +

    Visual fidelity is necessary. Native structure is non-negotiable.

    +

    A generated deck can match the reference image and still collapse the moment someone edits a chart, applies a layout, changes a theme, or reads the file with another tool. Gloss grades both layers.

    + Read the open scoring contract +
    +
    +
    Rendered pixels108
    +
    The artifact twistinside the .pptx
    +
    Object structure101
    +
    Layouts & masters25
    +
    Package safety22
    +
    Text semantics20
    +
    Asset hashes4
    +

    Candidate checks by method. Counts come from preview-v1.json.

    +
    +
    + +
    + +
    + +
    +
    +

    Truth before leaderboard

    +

    Working harness. Unfrozen benchmark.

    +

    Gloss is ready for public collaboration, not official model ranking. The release validator fails closed until independent evidence and frozen artifacts exist.

    +
    +
    +
    Candidate corpus validates

    280 schema-valid checks and 381 traceable prompt clauses.

    passing
    +
    Mutation operators execute

    280 controls pass; 280 generated single-fault mutations are detected.

    passing
    +
    Independent evidence

    Assertion provenance and evidence remain incomplete for 280 candidate checks.

    open
    +
    Release freeze

    Prompt convergence, reviewer approvals, baselines, manifests, and signed release indexes remain open.

    open
    +
    +
    + +
    +
    +

    Reproduce it locally

    +

    Trust the command, not the claim.

    +
    +
    +
    Terminal
    +
    git clone https://github.com/aronchick/gloss.git
    +cd gloss/acidslide-v1/grader
    +uv sync --extra dev --locked
    +uv run python ../benchmark/validate_corpus.py
    +uv run pytest tests/test_mutation_fixtures.py -q
    +

    +
    +
    + +
    + +
    +

    Gloss is built in public

    +

    Make generated decks worth editing.

    +
    + Join on GitHub +
    +
    + + + + diff --git a/site/media/gloss-launch-poster.png b/site/media/gloss-launch-poster.png new file mode 100644 index 0000000..724f916 Binary files /dev/null and b/site/media/gloss-launch-poster.png differ diff --git a/site/media/gloss-launch.mp4 b/site/media/gloss-launch.mp4 new file mode 100644 index 0000000..4782589 Binary files /dev/null and b/site/media/gloss-launch.mp4 differ diff --git a/site/site.css b/site/site.css new file mode 100644 index 0000000..1b2f0e1 --- /dev/null +++ b/site/site.css @@ -0,0 +1,339 @@ +:root { + --canvas: #f4f6fa; + --paper: #ffffff; + --ink: #171a22; + --muted: #626a79; + --rule: #c9ced8; + --orange: #d35230; + --orange-soft: #f7ded5; + --package: #2859d6; + --package-soft: #dfe8ff; + --proof: #b7f36b; + --display: "Aptos Display", "Arial Narrow", "Segoe UI", sans-serif; + --body: "Aptos", "Segoe UI", Helvetica, Arial, sans-serif; + --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --shell: min(92rem, calc(100vw - 3rem)); +} + +* { box-sizing: border-box; } +html { scroll-behavior: smooth; } +body { + margin: 0; + background: var(--canvas); + color: var(--ink); + font: 400 17px/1.55 var(--body); + -webkit-font-smoothing: antialiased; +} +button, input { font: inherit; } +a { color: inherit; } +svg { display: block; } +[hidden] { display: none !important; } + +.skip-link { + position: fixed; + z-index: 100; + top: 1rem; + left: 1rem; + padding: .75rem 1rem; + background: var(--ink); + color: white; + transform: translateY(-200%); +} +.skip-link:focus { transform: none; } +:focus-visible { outline: 3px solid var(--package); outline-offset: 4px; } + +.site-header { + position: relative; + z-index: 10; + display: flex; + align-items: center; + justify-content: space-between; + gap: 2rem; + width: var(--shell); + margin: 0 auto; + min-height: 5rem; + border-bottom: 1px solid var(--rule); +} +.wordmark { + display: inline-flex; + align-items: center; + gap: .7rem; + color: var(--ink); + font: 750 1.35rem/1 var(--display); + letter-spacing: -.045em; + text-decoration: none; +} +.wordmark-icon { + position: relative; + display: inline-block; + width: 1.8rem; + height: 1.55rem; + border: 2px solid var(--ink); + background: var(--paper); +} +.wordmark-icon i { position: absolute; width: 3px; background: var(--ink); bottom: 3px; } +.wordmark-icon i:nth-child(1) { left: 4px; height: 6px; } +.wordmark-icon i:nth-child(2) { left: 10px; height: 10px; } +.wordmark-icon i:nth-child(3) { left: 16px; height: 14px; background: var(--orange); } +.site-header nav { display: flex; align-items: center; gap: 1.8rem; font: 650 .77rem/1 var(--mono); } +.site-header nav > a { text-decoration: none; } +.site-header nav > a:not(.nav-cta) { color: #4e5664; } +.site-header nav > a:not(.nav-cta):hover { color: var(--package); } +.nav-cta { + display: inline-flex; + align-items: center; + gap: .45rem; + padding: .7rem .8rem; + border: 1px solid var(--ink); + background: var(--ink); + color: white; +} +.nav-cta svg, .button svg { width: 1.05rem; fill: currentColor; } + +.hero { + display: grid; + grid-template-columns: minmax(0, 1.08fr) minmax(26rem, .92fr); + align-items: center; + gap: clamp(3rem, 7vw, 8rem); + width: var(--shell); + margin: 0 auto; + padding: clamp(5rem, 9vw, 9rem) 0 clamp(4rem, 7vw, 7rem); +} +.hero-copy { max-width: 48rem; } +.eyebrow { + display: flex; + align-items: center; + gap: .55rem; + margin: 0 0 1.25rem; + color: #505866; + font: 700 .72rem/1.3 var(--mono); + letter-spacing: .055em; + text-transform: uppercase; +} +.status-dot { width: .58rem; height: .58rem; border-radius: 50%; background: var(--proof); box-shadow: 0 0 0 3px #dfffb5; } +h1, h2, h3 { margin-top: 0; font-family: var(--display); letter-spacing: -.055em; } +h1 { + max-width: 10ch; + margin-bottom: 1.8rem; + font-size: clamp(4.3rem, 7.4vw, 8.5rem); + font-weight: 780; + line-height: .86; +} +h1 span { display: inline-block; color: var(--orange); } +.lede { max-width: 39rem; margin: 0; color: #454d5b; font-size: clamp(1.08rem, 1.5vw, 1.36rem); line-height: 1.5; } +.lede strong { color: var(--ink); font-weight: 700; } +.hero-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2.4rem; } +.button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: .55rem; + min-height: 3.3rem; + padding: 0 1.15rem; + border: 1px solid var(--ink); + font: 700 .77rem/1 var(--mono); + text-decoration: none; + transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease; +} +.button:hover { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 var(--ink); } +.button-primary { background: var(--ink); color: white; } +.button-secondary { background: transparent; } +.hero-note { margin: 1.25rem 0 0; color: #6c7380; font: .68rem/1.5 var(--mono); } + +.xray { border: 1px solid var(--ink); background: var(--paper); box-shadow: 14px 14px 0 var(--ink); } +.xray-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 3.2rem; padding: .55rem .7rem; border-bottom: 1px solid var(--rule); background: #e9ecf2; } +.xray-tabs { display: flex; gap: .35rem; } +.xray-tab { + padding: .57rem .72rem; + border: 1px solid transparent; + background: transparent; + color: #565e6b; + font: 700 .66rem/1 var(--mono); + cursor: pointer; +} +.xray-tab.is-active { border-color: var(--ink); background: var(--paper); color: var(--ink); box-shadow: 2px 2px 0 var(--ink); } +.xray-file { color: #68717f; font: .65rem var(--mono); } +.xray-stage { min-height: 34rem; padding: 2rem; background-image: linear-gradient(#e3e6ec 1px, transparent 1px), linear-gradient(90deg, #e3e6ec 1px, transparent 1px); background-size: 18px 18px; } +.xray-view { animation: reveal 360ms cubic-bezier(.2,.8,.2,1); } +@keyframes reveal { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } } +.canvas-view { display: grid; grid-template-rows: 1fr auto; min-height: 30rem; } +.slide-art { + position: relative; + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + align-self: center; + padding: 8% 8%; + background: var(--ink); + color: white; + box-shadow: 0 10px 24px rgb(23 26 34 / .2); +} +.slide-art::after { content: ""; position: absolute; width: 9rem; height: 9rem; right: -3.5rem; top: -3.5rem; border: 1.7rem solid var(--orange); transform: rotate(14deg); } +.slide-kicker { color: #b9c2d4; font: 700 .52rem var(--mono); letter-spacing: .12em; } +.slide-title { margin-top: 6%; font: 760 clamp(1.35rem, 3vw, 2.3rem)/.92 var(--display); letter-spacing: -.04em; } +.slide-rule { width: 42%; height: 4px; margin-top: 7%; background: var(--orange); } +.slide-chart { position: absolute; display: flex; align-items: flex-end; gap: 4%; width: 33%; height: 35%; right: 8%; bottom: 14%; border-bottom: 1px solid #798296; } +.slide-chart i { width: 17%; height: var(--h); background: #f4f6fa; } +.slide-chart i:last-child { background: var(--orange); } +.slide-caption { position: absolute; right: 8%; bottom: 7%; color: #aab3c3; font: .48rem var(--mono); } +.xray-caption { margin: 1.2rem 0 0; color: #626a77; font: .72rem/1.4 var(--mono); } +.xray-caption b { color: var(--ink); } +.package-view { min-height: 30rem; background: var(--paper); border: 1px solid var(--ink); box-shadow: 8px 8px 0 var(--package); } +.package-head { display: flex; justify-content: space-between; gap: 1rem; padding: 1rem; border-bottom: 1px solid var(--ink); font: .7rem var(--mono); } +.package-head strong { color: var(--package); } +.package-tree { margin: 0; padding: 1rem 0; list-style: none; font: .72rem/1.4 var(--mono); } +.package-tree li { display: grid; grid-template-columns: 1rem 1fr auto; gap: .45rem; min-height: 2.35rem; align-items: center; padding: .2rem 1rem; border-bottom: 1px solid #e6e8ed; } +.package-tree em { color: #777f8c; font-style: normal; } +.package-tree .tree-depth-1 { padding-left: 2rem; } +.package-tree .tree-depth-2 { padding-left: 3rem; } +.package-tree .is-hot { background: var(--package-soft); color: #153a97; } +.package-tree .is-hot em { color: #4263ad; } +.tree-toggle, .file-icon { color: var(--package); } +.package-view .xray-caption { padding: 0 1rem 1rem; } +.xray-foot { display: flex; justify-content: space-between; gap: 1rem; padding: .75rem 1rem; border-top: 1px solid var(--rule); color: #626a77; font: .61rem var(--mono); } + +.proof-band { display: grid; grid-template-columns: 1.15fr repeat(4, 1fr); border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); background: var(--paper); } +.proof-cell { display: flex; min-height: 10.5rem; flex-direction: column; justify-content: space-between; padding: 1.25rem; border-right: 1px solid var(--rule); text-decoration: none; } +.proof-cell:last-child { border-right: 0; } +.proof-label { color: #646c79; font: 700 .63rem var(--mono); letter-spacing: .05em; text-transform: uppercase; } +.proof-cell strong { font: 760 clamp(2.1rem, 3.7vw, 4rem)/1 var(--display); letter-spacing: -.05em; } +.proof-cell > span:last-child { color: #636b78; font: .68rem var(--mono); } +.proof-lead { background: var(--ink); color: white; } +.proof-lead .proof-label, .proof-lead > span:last-child { color: #bfc6d3; } +.proof-lead:hover { background: var(--package); } +.proof-warning { background: var(--orange-soft); } +.proof-warning strong { color: #a53920; } + +.section-shell { width: var(--shell); margin: 0 auto; } +.section-heading { max-width: 52rem; } +.section-heading h2, .method h2, .status h2, .reproduce h2 { + margin-bottom: 1.5rem; + font-size: clamp(3.3rem, 6.2vw, 7.2rem); + font-weight: 760; + line-height: .92; +} +.section-heading > p:last-child, .method-copy > p:not(.eyebrow), .status-intro > p:last-child { max-width: 43rem; color: #59616e; font-size: 1.08rem; } +.launch-film { padding: clamp(7rem, 12vw, 13rem) 0; } +.film-frame { width: min(68rem, 100%); margin: 4rem auto 0; padding: 1rem; border: 1px solid var(--ink); background: var(--paper); box-shadow: 14px 14px 0 var(--orange); } +.film-frame video { display: block; width: 100%; aspect-ratio: 1; background: var(--ink); } +.film-meta { display: flex; flex-wrap: wrap; gap: 1.3rem; padding: 1rem .25rem 0; color: #656d7a; font: .65rem var(--mono); } +.film-meta a { margin-left: auto; color: var(--package); } + +.method { display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(4rem, 9vw, 10rem); align-items: start; padding: 2rem 0 clamp(8rem, 13vw, 14rem); } +.method h2 { font-size: clamp(3.2rem, 5.4vw, 6rem); } +.text-link { display: inline-flex; gap: .5rem; margin-top: 1rem; color: var(--package); font: 700 .75rem var(--mono); text-underline-offset: .25rem; } +.method-list { padding-top: .8rem; } +.method-row { display: grid; grid-template-columns: 10rem 1fr 2.6rem; gap: 1rem; align-items: center; min-height: 3.5rem; border-bottom: 1px solid var(--rule); font: .72rem var(--mono); } +.method-row i { height: .75rem; width: calc(var(--value) / 108 * 100%); background: var(--package); } +.method-row b { text-align: right; } +.method-row-visual i { background: var(--orange); } +.method-divider { display: flex; justify-content: space-between; gap: 1rem; padding: 1.6rem 0 .6rem; color: var(--package); font: 750 .65rem var(--mono); text-transform: uppercase; } +.method-divider em { color: #747c89; font-style: normal; text-transform: none; } +.method-list > p { color: #777f8b; font: .63rem/1.5 var(--mono); } + +.collaborate { border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); background: var(--ink); color: white; } +.collaborate-inner { padding: clamp(7rem, 11vw, 12rem) 0; } +.collaborate .eyebrow { color: var(--proof); } +.collaborate .section-heading > p:last-child { color: #b8c0ce; } +.contribution-grid { display: grid; grid-template-columns: repeat(3, 1fr); margin-top: 4rem; border-top: 1px solid #565e6c; border-left: 1px solid #565e6c; } +.contribution-card { display: flex; min-height: 25rem; flex-direction: column; padding: 1.5rem; border-right: 1px solid #565e6c; border-bottom: 1px solid #565e6c; text-decoration: none; transition: background 150ms ease, color 150ms ease; } +.contribution-card:hover { background: var(--proof); color: var(--ink); } +.card-index { color: #9ba4b2; font: .67rem var(--mono); } +.contribution-card:hover .card-index { color: #40501f; } +.contribution-card h3 { max-width: 10ch; margin: 3.5rem 0 1.2rem; font-size: 2.3rem; line-height: .98; } +.contribution-card p { color: #afb7c4; } +.contribution-card:hover p { color: #36411e; } +.card-action { margin-top: auto; color: var(--proof); font: 700 .69rem var(--mono); } +.contribution-card:hover .card-action { color: var(--ink); } +.repo-paths { display: grid; grid-template-columns: repeat(4, 1fr); margin-top: 2rem; gap: .75rem; } +.repo-paths a { padding: .85rem; border: 1px solid #4b5360; color: #dce1ea; font: .62rem var(--mono); text-decoration: none; } +.repo-paths a:hover { border-color: var(--proof); color: var(--proof); } +.repo-paths span { color: #777f8d; } + +.status { display: grid; grid-template-columns: .82fr 1.18fr; gap: clamp(4rem, 9vw, 10rem); padding: clamp(8rem, 13vw, 14rem) 0; } +.status h2 { font-size: clamp(3.2rem, 5.4vw, 6.2rem); } +.gate-list { border-top: 1px solid var(--ink); } +.gate { display: grid; grid-template-columns: 2rem 1fr auto; gap: 1rem; align-items: start; padding: 1.35rem 0; border-bottom: 1px solid var(--rule); } +.gate-icon { display: grid; width: 1.45rem; height: 1.45rem; place-items: center; border: 1px solid var(--ink); font: 700 .7rem var(--mono); } +.gate strong { font-size: 1rem; } +.gate p { margin: .25rem 0 0; color: #69717e; font-size: .88rem; } +.gate em { padding: .26rem .45rem; border: 1px solid currentColor; font: 700 .6rem var(--mono); font-style: normal; text-transform: uppercase; } +.gate-pass .gate-icon, .gate-pass em { color: #38601d; background: #ddf7bd; } +.gate-open .gate-icon, .gate-open em { color: #99412b; background: var(--orange-soft); } + +.reproduce { display: grid; grid-template-columns: .75fr 1.25fr; gap: clamp(3rem, 9vw, 10rem); align-items: start; padding-bottom: clamp(8rem, 13vw, 14rem); } +.reproduce h2 { font-size: clamp(3.2rem, 5vw, 5.8rem); } +.command-block { border: 1px solid var(--ink); background: var(--ink); color: white; box-shadow: 10px 10px 0 var(--package); } +.command-head { display: flex; justify-content: space-between; align-items: center; min-height: 2.9rem; padding: 0 .9rem; border-bottom: 1px solid #424957; color: #aeb6c5; font: .65rem var(--mono); } +.command-head button { border: 1px solid #656d7a; padding: .35rem .55rem; background: transparent; color: white; font: .62rem var(--mono); cursor: pointer; } +.command-block pre { overflow-x: auto; margin: 0; padding: 1.4rem; color: #e7ebf2; font: .73rem/1.85 var(--mono); } +.command-block pre code::first-line { color: var(--proof); } +.command-block > p { min-height: 1.2rem; margin: 0; padding: 0 1.4rem 1rem; color: var(--proof); font: .61rem var(--mono); } + +.final-cta { display: grid; grid-template-columns: auto 1fr auto; gap: 2rem; align-items: center; padding: clamp(4rem, 7vw, 7rem) max(1.5rem, calc((100vw - min(92rem, calc(100vw - 3rem))) / 2)); border-top: 1px solid var(--ink); background: var(--orange); color: white; } +.final-cta .eyebrow { color: #ffe3da; } +.final-cta h2 { max-width: 14ch; margin: 0; font-size: clamp(2.4rem, 5vw, 5rem); line-height: .95; } +.final-cta .button-primary { background: white; color: var(--ink); } +.final-mark { position: relative; display: grid; width: clamp(5rem, 9vw, 8rem); aspect-ratio: 1; place-items: center; border: 2px solid white; font: 800 clamp(2.5rem, 5vw, 4.5rem) var(--display); } +.final-mark i { position: absolute; right: 10%; bottom: 10%; width: 6%; background: white; } +.final-mark i:nth-of-type(1) { height: 18%; right: 25%; } +.final-mark i:nth-of-type(2) { height: 28%; right: 15%; } +.final-mark i:nth-of-type(3) { height: 40%; right: 5%; background: var(--ink); } + +.site-footer { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 2rem; width: var(--shell); min-height: 6.5rem; margin: 0 auto; color: #656d79; font: .62rem var(--mono); } +.site-footer p { margin: 0; text-align: center; text-transform: uppercase; letter-spacing: .04em; } +.site-footer > div { display: flex; gap: 1rem; } +.site-footer > div a { text-underline-offset: .2rem; } + +@media (max-width: 1000px) { + .site-header nav > a:not(.nav-cta) { display: none; } + .hero { grid-template-columns: 1fr; } + .hero-copy { max-width: 52rem; } + .xray { width: min(42rem, calc(100% - 1rem)); margin: 0 auto; } + .proof-band { grid-template-columns: repeat(2, 1fr); } + .proof-cell { border-bottom: 1px solid var(--rule); } + .proof-lead { grid-column: 1 / -1; } + .method, .status, .reproduce { grid-template-columns: 1fr; } + .method-copy, .status-intro, .reproduce > div:first-child { max-width: 48rem; } + .contribution-grid { grid-template-columns: 1fr; } + .contribution-card { min-height: 18rem; } + .repo-paths { grid-template-columns: repeat(2, 1fr); } +} + +@media (max-width: 640px) { + :root { --shell: calc(100vw - 2rem); } + body { font-size: 16px; } + .site-header { min-height: 4.4rem; } + .nav-cta span { display: none; } + .hero { padding-top: 4rem; } + h1 { font-size: clamp(3.8rem, 18vw, 5.5rem); } + .hero-actions .button { width: 100%; } + .xray { width: calc(100% - .6rem); box-shadow: 8px 8px 0 var(--ink); } + .xray-stage { min-height: 28rem; padding: .8rem; } + .canvas-view, .package-view { min-height: 26rem; } + .xray-file { display: none; } + .package-tree { font-size: .62rem; } + .package-tree em { display: none; } + .package-tree li { grid-template-columns: 1rem 1fr; } + .proof-band { grid-template-columns: 1fr; } + .proof-lead { grid-column: auto; } + .proof-cell { min-height: 8.5rem; } + .section-heading h2, .method h2, .status h2, .reproduce h2 { font-size: clamp(3rem, 15vw, 4.5rem); } + .film-frame { padding: .5rem; box-shadow: 8px 8px 0 var(--orange); } + .film-meta a { width: 100%; margin: 0; } + .method-row { grid-template-columns: 8rem 1fr 2rem; gap: .55rem; font-size: .62rem; } + .repo-paths { grid-template-columns: 1fr; } + .gate { grid-template-columns: 1.6rem 1fr; } + .gate > em { grid-column: 2; justify-self: start; } + .command-block { box-shadow: 7px 7px 0 var(--package); } + .final-cta { grid-template-columns: 1fr; } + .final-mark { width: 5rem; } + .final-cta .button { width: 100%; } + .site-footer { grid-template-columns: 1fr; gap: 1rem; padding: 2rem 0; } + .site-footer p { text-align: left; } +} + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; } +} diff --git a/site/site.js b/site/site.js new file mode 100644 index 0000000..ffc9269 --- /dev/null +++ b/site/site.js @@ -0,0 +1,75 @@ +const xray = document.querySelector(".xray"); +const xrayButtons = [...document.querySelectorAll("[data-xray-target]")]; +const xrayPanels = [...document.querySelectorAll("[data-xray-panel]")]; +let xrayTimer; + +function showXrayLayer(layer, { userInitiated = false } = {}) { + if (!xray) return; + xray.dataset.xray = layer; + for (const button of xrayButtons) { + const active = button.dataset.xrayTarget === layer; + button.classList.toggle("is-active", active); + button.setAttribute("aria-pressed", String(active)); + } + for (const panel of xrayPanels) { + panel.hidden = panel.dataset.xrayPanel !== layer; + } + if (userInitiated) window.clearTimeout(xrayTimer); +} + +for (const button of xrayButtons) { + button.addEventListener("click", () => showXrayLayer(button.dataset.xrayTarget, { userInitiated: true })); +} + +const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; +if (!reducedMotion) { + xrayTimer = window.setTimeout(() => showXrayLayer("package"), 1500); +} + +const evidenceBindings = { + "candidate-checks": (data) => data.candidate_checks.total, + "visual-checks": (data) => data.candidate_checks.visual_render, + "inside-file-checks": (data) => data.candidate_checks.inside_file, + "inside-file-percent": (data) => data.candidate_checks.inside_file_percent, + "positive-passed": (data) => data.operator_evidence.positive_controls_passed, + "positive-total": (data) => data.operator_evidence.positive_controls, + "mutants-detected": (data) => data.operator_evidence.single_fault_mutations_detected, + "mutants-total": (data) => data.operator_evidence.single_fault_mutations, +}; + +fetch("/evidence/preview-v1.json") + .then((response) => { + if (!response.ok) throw new Error(`Evidence request failed: ${response.status}`); + return response.json(); + }) + .then((data) => { + document.documentElement.dataset.evidenceId = data.evidence_id; + for (const [key, readValue] of Object.entries(evidenceBindings)) { + for (const node of document.querySelectorAll(`[data-evidence="${key}"]`)) { + node.textContent = String(readValue(data)); + } + } + }) + .catch(() => { + document.documentElement.dataset.evidenceId = "fallback-copy"; + }); + +const copyButton = document.querySelector("[data-copy-command]"); +const copyStatus = document.querySelector("[data-copy-status]"); +const command = document.querySelector(".command-block code"); + +if (copyButton && command) { + copyButton.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText(command.textContent.trim()); + copyButton.textContent = "Copied"; + if (copyStatus) copyStatus.textContent = "Commands copied to clipboard."; + window.setTimeout(() => { + copyButton.textContent = "Copy"; + if (copyStatus) copyStatus.textContent = ""; + }, 1800); + } catch { + if (copyStatus) copyStatus.textContent = "Select the commands and copy them manually."; + } + }); +} diff --git a/spec-output.md b/spec-output.md index 91ea72a..ece37cf 100644 --- a/spec-output.md +++ b/spec-output.md @@ -1,6 +1,12 @@ +# SUPERSEDED SNAPSHOT — DO NOT IMPLEMENT OR RELEASE + +This file is retained only as historical debate output. The canonical contract is +`ACIDSLIDE_OPENSPEC.md`, whose current status is Draft pending adversarial consensus. Regenerate this +snapshot only after the canonical document is freeze-ready and independently accepted. + # AcidSlide v1 OpenSpec -Status: Final (ECMA-376 architecture — 11 adversarial rounds, Claude Opus 4.6 + gpt-5.4) +Status: Superseded — stale pre-remediation contract; not freeze-ready Scope: Public benchmark, automated grading suite, and hosted evaluation service for slide generation fidelity Primary artifact: A fully public, machine-graded PowerPoint benchmark inspired by the ACID browser tests