Skip to content

migration: review Kuikly 2.24.0 staging3 replay - #109

Draft
bytemain wants to merge 242 commits into
mainfrom
staging3
Draft

migration: review Kuikly 2.24.0 staging3 replay#109
bytemain wants to merge 242 commits into
mainfrom
staging3

Conversation

@bytemain

@bytemain bytemain commented Aug 3, 2026

Copy link
Copy Markdown
Member

Purpose

Review-only Draft PR for task #73. This shows the complete net change required to move the bytemain fork from the current main baseline to the audited staging3 Kuikly 2.24.0 migration candidate.

Do not merge this PR until the product cutover strategy is explicitly approved. staging2 and the current Mobile gitlink/HAR remain the production path.

Exact coordinates

  • Base: main@1048ad0189ee4579bd9585d00b9623e3d4d6a125
  • Head: staging3@d37094f3a7e2e105d1959e2509dd1d3c5828f769
  • Head tree: 64d236099ddcaa2e405b98f137851fdc2fc1009f
  • Upstream baseline: Tencent-TDS/KuiklyUI 2.24.0@76a866795903014cfd2d0363ee31ccee7895775e
  • Frozen fork replay side: staging2@6a531a57105ee453edcfdc07a54d1bb1b4348431
  • Replay merge: 25cbc1fa25be4bba0ca800a67762a1f1317c5f25, with real parents c8f92f053fb60d6fe515b5e986e1c6fe2db775a0 and 6a531a57105ee453edcfdc07a54d1bb1b4348431 (not -s ours)

Migration shape

  1. Start from the exact upstream 2.24.0 tag.
  2. Explicitly hold unsafe/not-yet-consumed upstream migrations before replay:
    • LazyList prefetch/runtime 1.9 bundle
    • dedicated iOS context thread
    • Pager snap/touch-defer lifecycle
    • PullToRefresh inset shortcut
  3. Replay the frozen fork's net retained behavior through a real two-parent merge, resolving nine cross-platform conflicts deliberately.
  4. Repair upstream fix: round layout size up to 2 decimals on size report-back Tencent-TDS/KuiklyUI#1588 layout-size report rounding on Android, Web, iOS, and OHOS, with boundary and unresolved-width tests.
  5. Add an exact-head migration manifest, ancestry/DCO guard, and Linux/iOS/OHOS hosted matrix.

The detailed carried-patch inventory, held commits, conflict decisions, cutover gates, and rollback plan are in docs/migrations/staging3-2.24.0.md.

Exact-head evidence

Dedicated run: https://github.com/bytemain/KuiklyUI/actions/runs/30790072289 — terminal SUCCESS for exact head d37094f3….

  • identity/ancestry: job 91611523845
  • source contracts: job 91611523856
  • Linux common/Compose/Android/Web: job 91611523886 — 162 / 85 / 2 tests, zero failures or errors
  • iOS: job 91611523880 — Xcode 16.2, locked Pods, Kotlin/Native main/tests, native fixtures, production renderer with warnings as errors
  • OHOS: job 91611523905 — pinned container, fixtures, HAR assembly, fresh AArch64 production direct-link
  • aggregate exact matrix: job 91612353738

Review boundary

  • No staging2 change.
  • No Mobile gitlink/HAR pin change.
  • No product artifact or coordinate publication; hosted uploads are evidence only.
  • No product runtime/cutover claim is made by this PR.
  • Any head change invalidates the exact matrix above and requires a wholly fresh exact-head run.

Please review the migration diff and the carried/held decisions. Merge/cutover remains a separate explicit decision.

bytemain and others added 30 commits June 18, 2026 22:12
V2 styled string nodes are rendered by ArkUI Text internally. Registering the legacy foreground-draw callback for those nodes can route them through OH_Drawing_TypographyPaint before the paragraph is layout-ready, which spams paragraph-is-not-formatted warnings.

Track the styled-string path on KRRichTextView, unregister/skip foreground draw for that path, and reset styled-string state when falling back to the legacy typography path.
Throttle Compose↔Native scroll sync (calc/expand deferral, contentSize
dedup, scrollEnd finalize), quantize ArkUI onScroll in fling, and draw
RichText when typography is ready during main-thread tasks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Quantize ArkUI scroll callbacks and SubcomposeLayout deltas at 0.5px,
dedupe content size updates, and flush the final offset on scroll stop.
Add OHOS demo cold-start page params and a CanScrollForward repro page.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ess test

Add a 500-item repeated demo list with Card UI and inspector enabled to reproduce and profile HarmonyOS scroll performance locally.

Co-authored-by: Cursor <cursoragent@cursor.com>
Clamp ArkUI scroll-frame-begin offset at nested list edges and skip
compose-side expand/offset correction when nestedScroll is configured.

Co-authored-by: Cursor <cursoragent@cursor.com>
Only recalculate native content size when contentView main-axis height
changes during fling, avoiding ~650 redundant calc calls per gesture
while keeping near-bottom and scrollEnd sync unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
Extend KuiklyScrollTrace with remeasure, frame timing, and offset/drag
skip metrics for OHOS scroll stress validation; gate redundant
contentOffset and isDragging writes; skip resetViewVisible when unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 10, 2026 16:59 — with GitHub Actions Failure
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 10, 2026 17:04 — with GitHub Actions Failure
@bytemain
bytemain temporarily deployed to raft-artifacts-production August 10, 2026 17:08 — with GitHub Actions Inactive
Signed-off-by: Argus <argus@mail.build>
Co-authored-by: Argus <argus@mail.build>
@bytemain
bytemain temporarily deployed to raft-artifacts-production August 10, 2026 17:59 — with GitHub Actions Inactive
Signed-off-by: Argus <argus@mail.build>
Co-authored-by: Argus <argus@mail.build>
@bytemain
bytemain temporarily deployed to raft-artifacts-production August 11, 2026 12:13 — with GitHub Actions Inactive
BiSheng and others added 6 commits August 11, 2026 12:26
Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
[task #93] Add immutable Kuikly Raft release set

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
Co-authored-by: BiSheng <raft-mobile-bisheng@mail.build>
Pin the protected Task93 writer to the exact terminal candidate run's five producer shards.

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
Restrict publish-mode Raft-exclusive Kotlin predecessors to the two public task #127 runtime modules, while compiler/toolchain dependencies retain the existing Tencent authority.

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
Skip producer and candidate jobs in writer mode, and start the publish job only after contract success plus exact skipped-result checks. The writer continues to use the frozen candidate run shards.

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 12:42 — with GitHub Actions Failure
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 12:46 — with GitHub Actions Failure
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 12:48 — with GitHub Actions Error
Signed-off-by: Lin Zhou <raft-mobile-linzhou@mail.build>
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 20:35 — with GitHub Actions Failure
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 20:37 — with GitHub Actions Failure
Signed-off-by: Lin Zhou <raft-mobile-linzhou@mail.build>
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 12, 2026 20:55 — with GitHub Actions Error
Signed-off-by: artin <artin@cat.ms>
@bytemain
bytemain had a problem deploying to raft-artifacts-production August 13, 2026 07:22 — with GitHub Actions Failure
Signed-off-by: artin <artin@cat.ms>
@bytemain
bytemain deployed to raft-artifacts-production August 13, 2026 08:52 — with GitHub Actions Active
Task #141 follow-up to task #93. Freezes the 45-file closure for
org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0-KBA-002 and its
available-at kotlinx-coroutines-test-ohosarm64 module, with a Hosted
carrier that validates the contract and resolves the authority bytes
from an empty cache.

The authority supplies 50 files for these coordinates, not 45. The
difference is the root -kotlin-tooling-metadata.json plus its 4 checksum
sidecars, which take no part in dependency resolution and are absent
from Raft for the already-published sibling family. This task keeps that
family shape and mirrors 45; the gap is named in the manifest and bound
by contract as authority_files=50, because a create-only Maven write can
never be yanked while an absent file can always be added later.

The mirrored root resolves for OHOS targets only; non-OHOS available-at
platform modules are not mirrored here. Recorded, not incidental.

kotlin-stdlib 2.0.21-KBA-001 stays a conditional closure member and is
not published. Before the first PUT, a Raft-only empty-cache OHOS
consumer resolution must record the real dependency graph and the stdlib
finally selected.

Landing this source grants no publication authority. Publication remains
0 PUT until that gate passes.

Independent review: task #142 FINAL PASS / 0 blocker by CC-希乐 on exact
586df6f.

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
@bytemain
bytemain deployed to raft-artifacts-production August 19, 2026 05:33 — with GitHub Actions Active
Lands the mirror publication process in the repo so the next coordinate does not
have to rediscover it, per artin's request in #Kuiklybase:8d8d3ee7.

RUNBOOK.md records the traps that actually cost CI rounds: the authority serves
no directory listing and answers directory URLs with 200 plus a not-browseable
notice rather than 404; Raft answers some absent paths with 401, so 404 is not
the only absent signal; Raft serves no maven-metadata.xml, so only exact
versions resolve; carriers must be exactly one commit; and expected_sha must be
the landed staging3 tip, because squash-merging means the reviewed head is not
on staging3.

Two enumeration habits are recorded as actions rather than maxims: keep the
probe grid in the manifest header, and pair every zero-hit claim with a
known-present positive control.

stage_manifest.py materialises a frozen manifest into a local Maven layout with
per-byte verification, so a consumer can be exercised before an unyankable
write. It ships no consumer-side version check: such a check reads a build file
this repository does not own, and shipping it would imply coverage that does not
exist. That contract belongs to Mobile.

Independent review: task #143 FINAL PASS / 0 blocker by CC-希乐 on exact
0469c59, after they found and confirmed the
fix for a blocker where the removed consumer check had taken the exception class
with it, leaving every failure path raising NameError.

No writer, manifest or workflow is touched, so the task #141 45-file publication
receipt is unaffected.

Signed-off-by: BiSheng <raft-mobile-bisheng@mail.build>
Ports two iOS crash guards that landed on staging2 and that the Kuikly 2.24.0
staging3 replay did not carry.

Original authorship (metadata cannot hold it under the identity-diff gate,
which requires exactly one commit with author == committer):
  926462b fix(ios): guard optional render view method dispatch (#123)
  07b14b3 fix(ios): guard gradient rich text method forwarding (#124)
  both authored by Jiacheng on staging2, 2026-08-07

Independent review: LiBai — SOURCE GO bound to exact
5a5022d (file set, line-for-line content,
tree and DCO independently recomputed).

EVIDENCE TIERS — do not collapse these:
  source     transport fidelity verified (patches byte-identical to origin)
  artifact   change confirmed and isolated by control: of 34 archives in the
             release candidate, 33 are content-identical to the published set
             (differing only in packaging timestamps); the sole content
             difference is 2 entries in core-render-ios xcframework.zip, the
             compiled OpenKuiklyIOSRender binaries — this PR's expected output
  runtime    NOT RUN. No iOS build, simulator or device has exercised these
             guards. The crash exposure was established by reading the two
             call sites, never reproduced. There is currently no iOS physical
             execution seat.

KNOWN COVERAGE GAP:
  The KRGradientRichTextViewMethodDispatchTest fixture covers the
  KRGradientRichTextView guard only. The KuiklyRenderLayerHandler.mm view
  dispatch guard has NO test — deleting it leaves CI fully green. The
  ios-renderer job's green does not speak to that guard.
  The fixture is also compiled for the macOS host (-DTARGET_OS_OSX=1 + AppKit),
  so its pass proves the host dispatch contract, not iOS device behaviour.

The Task93 immutable-release-set workflow fails on this PR. That gate compares
byte equality while POMs embed the source commit SHA and archives embed build
timestamps, so it reports CONFLICT for any source change after publication and
carries no information about correctness. artin ruled it does not gate source
PRs (2026-08-21).
The candidate upload had no `if: always()`, so a failing "Assemble and preflight
the source-review candidate" step skipped the artifact upload and discarded
public-plan.json -- exactly in the case where it is the only thing that explains
the failure.

kuikly_maven_publish.py writes the full plan to disk and prints only a one-line
summary. That line cannot distinguish the four causes of CONFLICT; the
discriminating lists (unexpected / different / listingDisagreement) exist only
in the uploaded plan.

if-no-files-found relaxed to `warn` for the same step so that a failure early
enough to abort before the candidate directory exists cannot manufacture a
second, misleading failure on top of the real one. The release-receipt upload
at the end of this workflow already carried `if: always()`.

Verified on this PR's own failing run (32507129327): assemble-candidate failed
with `publication plan: CONFLICT present=920/920`, the upload step reported
success rather than skipped, and public-plan.json was retrievable from the
artifact -- yielding unexpected=0, different=485, listingDisagreement=0
directly, instead of requiring the five stage artifacts to be re-downloaded and
classify to be re-run by hand.

Independent review: LiBai -- GO bound to exact
604bacb, including confirming that SOURCE_SHA
is a workflow-level env and so is always populated on the newly-reachable
early-failure paths.

The Task93 workflow itself fails on this PR: it triggers on its own workflow
file, and its byte-equality criterion cannot hold once POMs embed the source
SHA. artin ruled (2026-08-21) that it does not gate source PRs.

Not addressed here, both needing a design decision: the `core-render-ios/**`
trigger pulling source PRs into a publication gate, and the byte-equality
criterion itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.