Skip to content

Vendor-pull slice 4c: isolate mobile Markdown image requests #143

Description

@gannonh

Status

Implemented

Goal

Mobile Markdown images never show stale content or accept stale callbacks when a rendered image source changes during thread updates.

Context

Parent: #124, vendor-pull slice 4.

Depends on #141 because this follow-up isolates the image renderer introduced there and touches the same ThreadFeed hotspot.

Source behavior: upstream #7942 at 55c909334.

Constraints and non-goals

  • Keep the intrinsic sizing, unavailable state, tap-to-view behavior, and source support from Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141.
  • Give each URI its own load state. Do not use a shared mutable URI guard.
  • Keep the image invisible until that request loads and show a non-interactive loading state meanwhile.
  • Do not add caching, prefetching, retry controls, or attachment upload.
  • Do not add a component-test dependency solely for this follow-up. The stale-event proof uses the public mobile flow with deterministic delayed responses.
  • Do not change web or desktop Markdown rendering.

Acceptance criteria

  • Replacing image URI A with URI B remounts the request so a late load or error from A cannot change B's size, visibility, or failure state.
  • Each image request owns its loaded state and remains hidden until its own load event succeeds.
  • A visible, non-interactive loading state occupies the image frame while the active request is pending.
  • Intrinsic sizing, direct and workspace sources, unavailable handling, and tap-to-view continue to satisfy Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141.
  • A deterministic delayed-response mobile fixture covers out-of-order load and error callbacks across a URI replacement.
  • Focused tests, the mobile typecheck, and a mobile walkthrough pass with no new T3 product identity.

Architecture

Extract the native <Image> request into a child keyed by URI. The child owns loading visibility and forwards only its own size or error result to the parent renderer.

No contract, server, persistence, desktop, or web changes.

Delivery slices

  1. Isolate each Markdown image request and prove stale events cannot affect its replacement.

Demonstration

  • Consumer: a Kata Code mobile user watching a thread update or switching between messages with remote images.
  • Action or input: render a delayed image, replace its URI before completion, and allow the old request to settle after the new one.
  • Observable result: only the current image becomes visible and its layout remains correct. The old request never flashes or marks the current image failed.
  • Evidence: the scripted test-t3-mobile delayed-response run and a recording or screenshot sequence.

Verification

  • Run vp test run packages/client-runtime/src/markdownImages.test.ts apps/mobile/src/features/threads/markdownImageSize.test.ts to preserve Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141's classifier and sizing behavior.
  • Run vp run --filter @kata-sh/code-mobile typecheck.
  • After maintainer authorization for simulator computer use, run the project test-t3-mobile flow with a deterministic responder that starts URI A, replaces it with URI B, settles B, then settles A with both late success and late error variants.
  • Make one bounded attempt to record the request replacement. If recording tooling is unavailable, retain before, loading, and final screenshots and flag the recording gap.
  • Search the product diff for @t3tools/, T3CODE_, T3 Code, and pingdotgg/t3code.

Risks and mitigations

  • Remounting can reset more state than intended. Keep request-local state inside the keyed child and sizing state in the parent.
  • The loading treatment can intercept taps or accessibility focus. Set it non-interactive and keep the active image's accessibility behavior unchanged.
  • This shares ThreadFeed with the first-open scroll fix. The native dependency keeps those ports out of the same file at the same time.

Build handoff

  • Approved scope: not approved yet. Proposed scope is upstream #7942 after Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141.
  • Non-goals: caching, retries, prefetch, attachments, and web or desktop Markdown.
  • Ordered slices: isolate the request, then prove late success and late error behavior through the deterministic mobile fixture.
  • Required verification commands: Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141's focused tests, mobile typecheck, delayed-response mobile walkthrough, bounded recording attempt, and identity search.
  • Fixtures or credentials needed: two deterministic delayed image URLs or local test responses.
  • Blocking open questions: None

Activity

  1. added
    enhancementRequested improvement or new capability.
    kind:sub-specChild spec produced by decomposing an epic.
    status:draftSpec is being written or revised. Do not build.
    phase:planCurrently in the Plan phase.
    on Aug 26, 2026
  2. gannonh commented on Aug 26, 2026

    @gannonh
    OwnerAuthor

    Adversarial spec review disposition

    Accepted the vague-verification finding. The spec now names #141's exact classifier and sizing test command, the mobile typecheck, and the delayed-response test-t3-mobile sequence that settles B before late success and late error events from A.

    No new component-test dependency was added solely for this follow-up. The repository has no existing mobile component-rendering test seam. The deterministic public mobile fixture proves the keyed request behavior at the user boundary.

  3. added
    status:approvedSpec approved by the maintainer. Ready to build.
    phase:buildCurrently in the Build phase.
    and removed
    status:draftSpec is being written or revised. Do not build.
    phase:planCurrently in the Plan phase.
    on Aug 29, 2026
  4. gannonh commented on Aug 29, 2026

    @gannonh
    OwnerAuthor

    Build started on branch 143-isolate-mobile-markdown-image-requests at base SHA 846775dc13d3babb3d9e007e9544ac9ebcfb107c. The maintainer requested autonomous implementation of the current approved issue scope. Cleared the stale closed dependency on #141.

  5. gannonh commented on Aug 29, 2026

    @gannonh
    OwnerAuthor

    Build report

    Implemented URI-keyed mobile Markdown image requests with request-local loading state and an unmount lifecycle guard for stale callbacks. Added a compile-gated mobile fixture, deterministic held-response server, and Maestro flow for late success and late error callbacks.

    Evidence:

    • 58 focused tests passed
    • mobile typecheck passed
    • changed-scope lint and format passed
    • iPhone 17 Pro / iOS 26.5 walkthrough passed both callback races with screenshots and video
    • isolated verify-katacode pairing regression passed
    • added-line T3 identity search returned no matches
    • independent spec review: PASS
    • independent code-quality review: Ready to continue

    Commit: ff12767

    Local artifacts: uat-evidence/issue-143-mobile and uat-evidence/web-20260829-213941-20d0ef6d

  6. added
    status:implementedBuilt and reported. Ready to verify.
    phase:verifyCurrently in the Verify phase.
    and removed
    status:approvedSpec approved by the maintainer. Ready to build.
    phase:buildCurrently in the Build phase.
    on Aug 29, 2026
  7. gannonh commented on Aug 29, 2026

    @gannonh
    OwnerAuthor

    Verification report

    All acceptance criteria pass on PR #154 at 54bd63800.

    • URI-keyed remount and child-local lifecycle guard reject stale A callbacks.
    • Each request owns loaded state and stays hidden until load.
    • The loading treatment is visible and non-interactive.
    • Vendor-pull slice 4a: preserve mobile Markdown image dimensions #141 sizing, source, unavailable, and viewer behavior remain intact.
    • Maestro dispatched captured late success and error handlers after B loaded; B remained visible and available.
    • 58 focused tests, mobile and scripts typechecks, lint, format, identity search, simulator walkthrough, and isolated web pairing regression passed.
    • Independent spec and code-quality reviews passed.
    • Current-head CI passed: Check, Test, Mobile Native Static Analysis, Release Smoke, and CodeRabbit.

    Status remains Implemented pending maintainer acceptance. PR: #154

  8. gannonh commented on Aug 29, 2026

    @gannonh
    OwnerAuthor

    Final PR-head verification for 4e37711:

    • 62 focused tests passed.
    • Mobile and scripts typechecks passed.
    • Targeted lint, formatting, and git diff --check passed.
    • The callback-delivery Maestro run passed both late-success and late-error cases on iPhone 17 Pro with iOS 26.5.
    • verify-katacode passed pairing and the web landing regression check on an isolated stack.
    • CI run 33278760862 passed Check, Test, Mobile Native Static Analysis, and Release Smoke.
    • All six inline review threads have explicit dispositions and are resolved.

    Issue status remains Implemented pending maintainer acceptance.

  9. gannonh commented on Aug 29, 2026

    @gannonh
    OwnerAuthor

    Final PR-head verification update for cca838e:\n\n- Fixed the pending-waiter HTTP lifecycle finding from the latest Codex review.\n- Focused responder checks passed.\n- CI run 33279211996 passed Check, Test, Mobile Native Static Analysis, and Release Smoke.\n- All PR review threads are resolved.\n\nIssue status remains Implemented pending maintainer acceptance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequested improvement or new capability.kind:sub-specChild spec produced by decomposing an epic.phase:verifyCurrently in the Verify phase.status:implementedBuilt and reported. Ready to verify.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions