{
  "schema_version": 1,
  "issue": 2699,
  "roadmap_issue": 530,
  "as_of": "2026-08-07",
  "authority": "Platform3 player implementation plus committed pinned-player fixture evidence",
  "definitions": {
    "registered_for_routing": "The Curriculum registry accepts the renderer_ref for the listed Content kind. Registration does not prove that the player can render every payload of that kind.",
    "verified_rendering": "The exact capability has implementation dispatch in the pinned player plus committed exact-shape good/adversarial fixtures and behavioral proof that the good shape renders while the invalid twin fails visibly or is rejected by its owning contract before routing.",
    "implemented_not_matrix_verified": "Implementation is present, but the required good/broken fixture pair has not been committed; consumers must not treat it as verified rendering."
  },
  "player": {
    "mutable_path": "/player/",
    "version": "2026-08-07.issue-2699-article-images",
    "pinned_path": "/player/versions/2026-08-07.issue-2699-article-images/",
    "fixture_manifest": "/player/fixtures/issue-530-a1/manifest.json",
    "feedback_fixture_manifest": "/player/fixtures/issue-1486/manifest.json",
    "interactive_lesson_fixture_manifest": "/player/fixtures/issue-1593-interactive-lesson/manifest.json",
    "test_bank_fixture_manifest": "/player/fixtures/issue-1922-test-bank/manifest.json",
    "graphic_gap_match_fixture_manifest": "/player/fixtures/issue-2511-graphic-gap-match/manifest.json",
    "article_html_block_fixture_manifest": "/player/fixtures/issue-2501-article-html/manifest.json",
    "choice_object_fallback_issue": 1678,
    "choice_object_fallback_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
    "test_bank_runtime_issue": 1922,
    "test_bank_runtime_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
    "pp100_attempt_issue": 2012,
    "pp100_event_identity_issue": 2136,
    "pp100_attempt_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
    "article_html_block_issue": 2501,
    "article_html_block_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
    "article_image_block_issue": 2699,
    "article_image_block_behavioral_test": "loop/player/tests/messageProtocol.test.mjs"
  },
  "summary": {
    "qti_item_interaction_coverage": "8/21",
    "qti_item_interactions_verified": 8,
    "qti_item_interactions_canonical_total": 21,
    "served_choice_object_fallback_verified": true,
    "qti_assessment_form_rendering_verified": true,
    "test_bank_rendering_verified": true,
    "governed_article_html_blocks_verified": true,
    "governed_article_image_blocks_verified": true,
    "all_registered_outputs_rendering_verified": false,
    "pp100_results_grading_verified": true
  },
  "renderer_routes": [
    {
      "renderer_ref": "renderer:interactive-lesson",
      "registered_for_routing": true,
      "accepted_content_kinds": [
        "article",
        "video",
        "interactive"
      ],
      "implementation_present": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "CONTENT_LOAD html bodies, governed article type=html and type=image blocks through the centralized sanitizer, plus typed interactive_article segment and interactive_video cue compositions with inline-QTI checkpoints; checkpoint QTI coverage inherits the 8/21 verified item interactions",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "article_html_block_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
        "article_image_block_behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
        "article_html_block_fixture_manifest": "site/player/fixtures/issue-2501-article-html/manifest.json",
        "article_html_block_good_fixture": "site/player/fixtures/issue-2501-article-html/article-html-block.good.json",
        "article_html_block_broken_fixture": "site/player/fixtures/issue-2501-article-html/article-html-block.broken.json",
        "article_publication_behavioral_test": "loop/content/artifacts/alpha/implementation/impl/tests/httpContracts.test.mjs",
        "fixture_manifest": "site/player/fixtures/issue-1593-interactive-lesson/manifest.json",
        "interactive_article_good_fixture": "site/player/fixtures/issue-1593-interactive-lesson/interactive-article.good.json",
        "interactive_article_broken_fixture": "site/player/fixtures/issue-1593-interactive-lesson/interactive-article.broken.json",
        "interactive_video_good_fixture": "site/player/fixtures/issue-1593-interactive-lesson/interactive-video.good.json",
        "interactive_video_broken_fixture": "site/player/fixtures/issue-1593-interactive-lesson/interactive-video.broken.json"
      },
      "note": "Verified by the issue-1593 composition fixtures, the issue-2501 exact article-block fixture pair, and the issue-2699 image-block behavioral contract against the pinned player and Content publication. HTML and image blocks enter the same centralized sanitizer; image URLs retain its HTTPS/data-image allowlist and authored alt text is escaped. The metadata-only article twin is rejected with typed 422 before trust, so it cannot become a silently blank lesson. The issue-1593 broken article fails visibly inside the checkpoint panel, and the broken video is loudly rejected at CONTENT_LOAD validation with a posted CONTENT_ERROR. interactive_video media playback is markup-pinned by the message-protocol harness; this route entry does not certify test/test_bank payloads (see renderer:qti-test)."
    },
    {
      "renderer_ref": "renderer:qti-item",
      "registered_for_routing": true,
      "accepted_content_kinds": [
        "question"
      ],
      "implementation_present": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "8/21 QTI item interaction types, including the bounded graphicGapMatch text-label/rect-target subset; canonical-QTI first, assessment-component distractor second, and strict public Content student-view fallbacks",
      "note": "A question route is not a claim that all QTI interaction types render. Unsupported interaction types fail loudly. Issue #1678 behaviorally verifies the final choice fallback against the exact {id, identifier, value, label, text} contract and visible rejection of malformed choices."
    },
    {
      "renderer_ref": "renderer:qti-test",
      "registered_for_routing": true,
      "accepted_content_kinds": [
        "test",
        "test_bank"
      ],
      "implementation_present": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "Exact-version Content test forms render their ordered question refs when every member uses one of the 8/21 verified item interactions. Exact-version test_bank launches require gateComponentId and studentId, delegate deterministic unseen-form selection to Curriculum next-form, verify the returned bank identity, and render only selected_form_ref.",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "fixture_manifest": "site/player/fixtures/issue-1922-test-bank/manifest.json",
        "good_fixture": "site/player/fixtures/issue-1922-test-bank/test-form.good.json",
        "broken_fixture": "site/player/fixtures/issue-1922-test-bank/test-form.broken.json",
        "behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
        "exact_student_view_endpoint": "/content/alpha/implementation/api/tenants/{tenantId}/alpha/content/items/{contentId}/student-view?version_id={contentVersionId}",
        "bank_selection_endpoint": "/curriculum/alpha/implementation/api/alpha/curriculum/v1/gates/{gateComponentId}/next-form?studentId={studentId}"
      },
      "note": "Test-bank membership remains Content-owned and form selection remains Curriculum-owned. The player carries no bank-selection algorithm and no second QTI engine; unsupported item interactions inside an otherwise valid form still fail visibly."
    }
  ],
  "container_capabilities": [
    {
      "id": "qtiAssessmentItem",
      "qti_root_element": "qti-assessment-item",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "8/21 interaction types"
    },
    {
      "id": "qtiAssessmentTestForm",
      "qti_root_element": "qti-assessment-test",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "Ordered exact-version question refs using the 8/21 verified item interactions",
      "evidence": {
        "fixture_manifest": "site/player/fixtures/issue-1922-test-bank/manifest.json",
        "good_fixture": "site/player/fixtures/issue-1922-test-bank/test-form.good.json",
        "broken_fixture": "site/player/fixtures/issue-1922-test-bank/test-form.broken.json",
        "behavioral_test": "loop/player/tests/messageProtocol.test.mjs"
      }
    },
    {
      "id": "testBank",
      "content_kind": "test_bank",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified_partial",
      "verified_scope": "Curriculum next-form selects one exact form from the requested exact bank; the player verifies the bank identity and renders the selected form under qtiAssessmentTestForm scope",
      "evidence": {
        "player_source": "site/player/player.js",
        "fixture_manifest": "site/player/fixtures/issue-1922-test-bank/manifest.json",
        "behavioral_test": "loop/player/tests/messageProtocol.test.mjs",
        "selection_owner": "Curriculum GET /alpha/curriculum/v1/gates/{gateComponentId}/next-form",
        "membership_owner": "Content exact-version test_bank and ordered bank_member references"
      }
    }
  ],
  "qti_item_interactions": [
    {
      "id": "choice",
      "qti_element": "qti-choice-interaction",
      "roadmap_stage": "baseline",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderChoiceInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/choice.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/choice.broken.xml",
        "authored_feedback_good_fixture": "site/player/fixtures/issue-1486/choice-feedback.good.xml",
        "authored_feedback_broken_fixture": "site/player/fixtures/issue-1486/choice-feedback.broken.xml",
        "choice_object_fallback_behavioral_test": "loop/player/tests/messageProtocol.test.mjs"
      }
    },
    {
      "id": "textEntry",
      "qti_element": "qti-text-entry-interaction",
      "roadmap_stage": "baseline",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderTextEntryInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/text-entry.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/text-entry.broken.xml"
      }
    },
    {
      "id": "order",
      "qti_element": "qti-order-interaction",
      "roadmap_stage": "A1",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderOrderInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/order.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/order.broken.xml"
      }
    },
    {
      "id": "match",
      "qti_element": "qti-match-interaction",
      "roadmap_stage": "A1",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderMatchInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/match.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/match.broken.xml"
      }
    },
    {
      "id": "inlineChoice",
      "qti_element": "qti-inline-choice-interaction",
      "roadmap_stage": "A1",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderInlineChoiceInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/inline-choice.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/inline-choice.broken.xml"
      }
    },
    {
      "id": "hottext",
      "qti_element": "qti-hottext-interaction",
      "roadmap_stage": "A1",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderHottextInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/hottext.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/hottext.broken.xml"
      }
    },
    {
      "id": "extendedText",
      "qti_element": "qti-extended-text-interaction",
      "roadmap_stage": "A1",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderExtendedTextInteraction",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "good_fixture": "site/player/fixtures/issue-530-a1/extended-text.good.xml",
        "broken_fixture": "site/player/fixtures/issue-530-a1/extended-text.broken.xml"
      }
    },
    {
      "id": "hotspot",
      "qti_element": "qti-hotspot-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "selectPoint",
      "qti_element": "qti-select-point-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "graphicOrder",
      "qti_element": "qti-graphic-order-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "graphicAssociate",
      "qti_element": "qti-graphic-associate-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "graphicGapMatch",
      "qti_element": "qti-graphic-gap-match-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": true,
      "rendering_state": "verified",
      "parser_symbol": "parseRenderableQtiXml",
      "renderer_symbol": "renderGraphicGapMatchInteraction",
      "verified_scope": "One packaged image, required nonblank alt plus positive dimensions, qti-gap-text labels with match-max=1, rect associable hotspots inside the graphic with match-max=1, bounded associations, and multiple directedPair responses. qti-gap-img and other geometry fail loudly.",
      "evidence": {
        "player_source": "site/player/player.js",
        "pinned_player_path": "/player/versions/2026-08-07.issue-2699-article-images/",
        "fixture_manifest": "site/player/fixtures/issue-2511-graphic-gap-match/manifest.json",
        "good_fixture": "site/player/fixtures/issue-2511-graphic-gap-match/graphic-gap-match.good.xml",
        "broken_fixture": "site/player/fixtures/issue-2511-graphic-gap-match/graphic-gap-match.broken.xml",
        "good_student_view_fixture": "site/player/fixtures/issue-2511-graphic-gap-match/student-view.good.json",
        "broken_student_view_fixture": "site/player/fixtures/issue-2511-graphic-gap-match/student-view.broken.json",
        "content_import_behavioral_test": "loop/content/artifacts/alpha/implementation/impl/tests/graphicGapMatchImport.test.mjs",
        "player_handoff_behavioral_test": "loop/player/tests/messageProtocol.test.mjs"
      },
      "note": "Synthetic APES-shaped capability evidence only. The real APES source activity remains ineligible until its producer supplies graph bytes, complete alternative text, label identifiers/text, and exact target geometry; Platform3 does not invent those facts or fall back to free text."
    },
    {
      "id": "positionObject",
      "qti_element": "qti-position-object-interaction",
      "roadmap_stage": "A2",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "slider",
      "qti_element": "qti-slider-interaction",
      "roadmap_stage": "A3",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "media",
      "qti_element": "qti-media-interaction",
      "roadmap_stage": "A3",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "endAttempt",
      "qti_element": "qti-end-attempt-interaction",
      "roadmap_stage": "A3",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "associate",
      "qti_element": "qti-associate-interaction",
      "roadmap_stage": "A3",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "gapMatch",
      "qti_element": "qti-gap-match-interaction",
      "roadmap_stage": "A3",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "drawing",
      "qti_element": "qti-drawing-interaction",
      "roadmap_stage": "A4",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "upload",
      "qti_element": "qti-upload-interaction",
      "roadmap_stage": "A4",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    },
    {
      "id": "portableCustom",
      "qti_element": "qti-portable-custom-interaction",
      "legacy_qti_element": "qti-custom-interaction",
      "roadmap_stage": "A4",
      "registered_for_routing": true,
      "verified_rendering": false,
      "rendering_state": "unsupported",
      "renderer_symbol": null,
      "failure_mode": "loud_rejection"
    }
  ]
}
