Repository navigation
Conversation
Signed-off-by: wangx700 <wangxin700@huawei.com>
Documentation build overview
69 files changed ·
|
There was a problem hiding this comment.
Code Review
This pull request introduces a sparse HCCL weight transfer engine for Ascend NPUs, enabling checkpoint-coordinate sparse weight updates during RLHF. It adds the necessary engine classes, validation logic, profiling diagnostics, and comprehensive unit and end-to-end tests. The feedback highlights a potential runtime error when checking NPU formats on CPU parameters, suggests a more compatible way to retrieve the current NPU stream, and identifies a parameter naming bug in the Qwen3 MoE example script.
| + @staticmethod | ||
| + def validate_checkpoint_weight_loader_view(layer): | ||
| + parameters = [getattr(layer, name, None) for name in ("w13_weight", "w2_weight")] | ||
| + if any(parameter is None for parameter in parameters): | ||
| + raise NotImplementedError("Checkpoint sparse updates require unsplit ND expert weights") | ||
| + if any(torch_npu.get_npu_format(parameter) not in (0, 2) for parameter in parameters): | ||
| + raise NotImplementedError("Checkpoint sparse updates require ND expert weights") |
There was a problem hiding this comment.
Calling torch_npu.get_npu_format on parameters without checking if they are on NPU can cause runtime errors (e.g., when parameters are on CPU during testing or initialization). Additionally, torch_npu might not be imported globally in this file. It is safer to import torch_npu locally and only check the NPU format for parameters that are actually on an NPU device.
@staticmethod
def validate_checkpoint_weight_loader_view(layer):
parameters = [getattr(layer, name, None) for name in ("w13_weight", "w2_weight")]
if any(parameter is None for parameter in parameters):
raise NotImplementedError("Checkpoint sparse updates require unsplit ND expert weights")
import torch_npu
for parameter in parameters:
if parameter.device.type == "npu":
if torch_npu.get_npu_format(parameter) not in (0, 2):
raise NotImplementedError("Checkpoint sparse updates require ND expert weights")
| + # ambient current device in the RPC thread. | ||
| + device = self.model_update_group.device | ||
| + with torch.npu.device(device): | ||
| + stream = torch.npu.current_stream(device=device) |
There was a problem hiding this comment.
Calling torch.npu.current_stream() without the device argument is more standard and compatible across different torch_npu versions. Since we are already inside the with torch.npu.device(device): context manager, the current device is already set, and current_stream() will automatically return the stream for that device.
stream = torch.npu.current_stream()
| + name = f"{prefix}.{expert}.gate_proj.weight" | ||
| + try: | ||
| + weight = model.get_parameter(name) | ||
| + except AttributeError: |
There was a problem hiding this comment.
In standard Hugging Face / Transformers implementations of Qwen3 MoE, the parameter name is gate_up_proj.weight (with the .weight suffix), similar to gate_proj.weight. Accessing gate_up_proj directly without the .weight suffix will raise an AttributeError on real models.
fused = model.get_parameter(f"{prefix}.gate_up_proj.weight")
…IME seam
vLLM-Ascend (#18915) and vLLM already carry the sparse weight-transfer pair:
SparseHCCLTrainerWeightTransferEngine (trainer/sender) and
SparseHCCLWeightTransferEngine (inference engine). docker/npu_patch/ instead
carried an older, self-contained variant of that engine plus a VIME-only
sparse_weight_patch module, so the shipped patch series did not match the code
that had been validated on A5.
Both patches were regenerated against the pinned bases (vllm e6bfe03ad,
vllm-ascend fd815467c from docker/npu_patch/README.md). Unrelated sections are
kept byte-identical so the review only shows real changes:
vllm-ascend.patch
- sparse_hccl_engine.py: 406-line bespoke engine -> the 160-line #18915 wrapper
that reuses vLLM's SparseNCCL* classes (trainer sends, inference receives).
- sparse_weight_patch.py: dropped, unused once the engine uses upstream
SparseWeightPatch.
- tests: take the #18915 unit test, e2e checkpoint test and rlhf example.
- worker.py / compute_slot_mappings.py: pick up the newer tree state (worker.py
had two incremental diffs in the old patch and is now a single section).
vllm.patch
- refresh checkpoint_weight_patch.py, reload/meta.py, glm4_moe_lite_mtp.py,
local_checkpoint.py and its unit test to the current tree state.
VIME seam (small, reuses the existing HF exporter):
- new sparse_diff_source.py diffs consecutive HF exports on the host and feeds
SparseWeightPatch to the sparse trainer engine; SparseTrainerAdapter exposes
the dense trainer surface (.client / .send_weights() / shutdown).
- --update-weight-transport gains "sparse_hccl"; the updater factory accepts it,
connect_rollout_engines picks create_sparse_trainer, and rollout engines get
weight_transfer_config={"backend": "sparse_hccl"}.
Role split is unchanged from upstream: the trainer engine sends, the
inference-side engine receives and applies through the native model loader.
Signed-off-by: A5 sync <wangxin700@huawei.com>
SparseNCCLTrainerWeightTransferEngine is sender-only (upstream: "Only the designated trainer sender joins the transfer group; other trainer ranks skip sparse sends"), but the adapter collected patches on every trainer rank. That kept one full host snapshot of the export per rank, i.e. tens of GB per trainer process that no rank but rank 0 can use. SparseTrainerAdapter.send_weights now returns early unless engine.is_sender, so non-sender ranks neither diff nor snapshot. Also drop the unused snapshot_in_host switch. Signed-off-by: A5 sync <wangxin700@huawei.com>
- tests/test_sparse_diff_source.py: the diff producer sends exactly the changed elements (int32 indices + BF16 values), the first sync is empty, an unchanged round is a no-op, non-sender ranks neither diff nor snapshot, and the draft flag is rejected instead of silently downgraded. - tests/test_update_weight_factory.py: add the sparse_hccl transport case so the factory keeps routing it to UpdateWeightFromDistributed. Both run on CPU; the diff tests import SparseWeightPatch from vLLM and skip when it is not installed. Signed-off-by: A5 sync <wangxin700@huawei.com>
…poke diff source The sparse HCCL backend already has a VIME-side implementation upstream in vime vllm-project#480 (head 1e46fc6) that this branch did not carry: a dedicated delta-mode updater with Megatron-side delta export, shard-batched gather and flush, and a sparse iterator bridge. PR vllm-project#492 shipped an older snapshot of the same Ascend branch minus those ten files, so a hand-rolled HF-export diff was being invented here instead of reusing them. Ported verbatim from vllm-project#480: - vime/backends/megatron_utils/update_weight/update_weight_from_sparse_hccl.py (436 lines, drives SparseHCCLTrainerWeightTransferEngine as the trainer sender; the inference side stays SparseHCCLWeightTransferEngine) - megatron_delta_export.py, delta_spec.py, delta_sync/{__init__,encode, sparse_gather}.py, hf_weight_iterator_sparse_bridge.py - scripts/run-qwen3-30B-A3B-sparse-hccl.sh, tests/test_sparse_hccl.py, tests/test_qwen3_30B_A3B_sparse_hccl_npu.py Wiring now matches vllm-project#480 exactly (sparse is a delta-mode transport, not a second full-mode carrier): - --update-weight-transport gains sparse_hccl, plus --update-weight-delta-batch-diff, --update-weight-delta-batch-gather and --update-weight-delta-verify-every - delta + sparse_hccl selects UpdateWeightFromSparseHCCL; delta stays disk|sparse_hccl - rollout engines get weight_transfer_config={"backend":"sparse_hccl"} when mode is delta and transport is sparse_hccl - update_weight_from_distributed.py is left untouched, so the dense nccl path is unchanged Removed: the hand-written sparse_diff_source.py and its unit test, plus the full-mode dispatch/transport edits, which vllm-project#480 supersedes. Signed-off-by: A5 sync <wangxin700@huawei.com>
…poke diff source The sparse HCCL backend already has a VIME-side implementation upstream in vime vllm-project#480 (head 1e46fc6) that this branch did not carry: a dedicated delta-mode updater with Megatron-side delta export, shard-batched gather and flush, and a sparse iterator bridge. PR vllm-project#492 shipped an older snapshot of the same Ascend branch minus those ten files, so a hand-rolled HF-export diff was being invented here instead of reusing them. Ported verbatim from vllm-project#480: - vime/backends/megatron_utils/update_weight/update_weight_from_sparse_hccl.py (436 lines, drives SparseHCCLTrainerWeightTransferEngine as the trainer sender; the inference side stays SparseHCCLWeightTransferEngine) - megatron_delta_export.py, delta_spec.py, delta_sync/{__init__,encode, sparse_gather}.py, hf_weight_iterator_sparse_bridge.py - scripts/run-qwen3-30B-A3B-sparse-hccl.sh, tests/test_sparse_hccl.py, tests/test_qwen3_30B_A3B_sparse_hccl_npu.py Wiring now matches vllm-project#480 exactly (sparse is a delta-mode transport, not a second full-mode carrier): - --update-weight-transport gains sparse_hccl, plus --update-weight-delta-batch-diff, --update-weight-delta-batch-gather and --update-weight-delta-verify-every - delta + sparse_hccl selects UpdateWeightFromSparseHCCL; delta stays disk|sparse_hccl - rollout engines get weight_transfer_config={"backend":"sparse_hccl"} when mode is delta and transport is sparse_hccl - update_weight_from_distributed.py is left untouched, so the dense nccl path is unchanged Removed: the hand-written sparse_diff_source.py and its unit test, plus the full-mode dispatch/transport edits, which vllm-project#480 supersedes.
68a80b7 to
31dc916
Compare
…, docs
- actor.py: with --offload-train and sparse_hccl the actor must wake and sleep
around the sync like a reconnecting rollout engine, because the sparse path
keeps live weights instead of going through the disk checkpoint.
- .buildkite/npu_suites.py: register test_qwen3_30B_A3B_sparse_hccl_npu.py and
test_sparse_hccl.py, and launch the latter through pytest since it owns its
distributed worker launch.
- docs/{en,zh}/advanced/delta-weight-sync.md: document sparse_hccl next to the
disk transport, including the batch/verify knobs and the TP2/PP2/EP2 caveat.
Signed-off-by: A5 sync <wangxin700@huawei.com>
docker/npu_patch/README.md installs the two dependency patches but never said what the sparse additions are for or how to switch them on, so an operator applying the series would not discover the non-shared-filesystem weight sync. Point at the trainer/inference engine split, the two flags, and the caveats. Signed-off-by: A5 sync <wangxin700@huawei.com>
31dc916 to
7c08a0b
Compare
The patch carried four Ascend model-execution changes that have nothing to do
with the sparse transport and that this PR does not need:
- device/device_op.py (int32 cast and empty-input guard in reshape_and_cache)
- ops/causal_conv1d.py (kernel flip for causal convolution)
- worker/v2/block_table.py and ops/triton/v2/block_table/compute_slot_mappings.py
(kernel_block_sizes plumbing, referenced only by each other)
Dropping them takes the patch from 19 files to 15 and keeps apply --check green
against the pinned vllm-ascend base. The four sparse files stay byte-identical
to vllm-ascend #18915 head, and every vllm/vllm_ascend import in the VIME sparse
updater still resolves against the patched trees.
The remaining eleven non-#18915 files are transfer plumbing that the sparse and
dense paths actually call:
- hccl_engine.py: HCCLTrainerWeightTransferEngine, used by sparse_hccl_engine.py
- pyhccl.py: PyHcclCommunicator.close(), called on communicator teardown
- __init__.py: registers sparse_hccl in both factories and hccl on the trainer
factory (vime maps backend nccl to hccl on NPU, so the dense trainer needs it)
- packed_tensor.py: packed broadcast, used by hccl_engine.py
- worker/worker.py and worker/v2/model_runner.py: start_weight_update under the
vLLM config, draft-model retargeting and the dict|list update payload that the
pinned vLLM protocol calls
- npu_ipc_engine.py: layerwise reload and batched load_weights for the npu_ipc
backend, the third registered transport in this series
- tests/e2e/pull_request/rlhf/{__init__,weight_transfer_test_utils}.py and the
routed_experts change: required by the ported #18915 tests
Signed-off-by: A5 sync <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
…rison Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Preserve existing IPC, packed transfer, worker and KV-cache fixes while retaining sparse HCCL additions. Signed-off-by: wangx700 <wangxin700@huawei.com>
Clarify Bridge full export naming, colocate gather queues and communication buffers, and inline export routing fields. Update tests and documentation for the simplified module layout. Signed-off-by: wangx700 <wangxin700@huawei.com>
Keep checkpoint loader views inside the sparse engine as in Ascend PR 18915, retaining the HCCL initialization API supported by the pinned dependency. Synchronize trainer failures at each gather queue boundary before another gather can start. Add distributed failure coverage and document the Bridge prerequisite. Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
…poke diff source The sparse HCCL backend already has a VIME-side implementation upstream in vime vllm-project#480 (head 1e46fc6) that this branch did not carry: a dedicated delta-mode updater with Megatron-side delta export, shard-batched gather and flush, and a sparse iterator bridge. PR vllm-project#492 shipped an older snapshot of the same Ascend branch minus those ten files, so a hand-rolled HF-export diff was being invented here instead of reusing them. Ported verbatim from vllm-project#480: - vime/backends/megatron_utils/update_weight/update_weight_from_sparse_hccl.py (436 lines, drives SparseHCCLTrainerWeightTransferEngine as the trainer sender; the inference side stays SparseHCCLWeightTransferEngine) - megatron_delta_export.py, delta_spec.py, delta_sync/{__init__,encode, sparse_gather}.py, hf_weight_iterator_sparse_bridge.py - scripts/run-qwen3-30B-A3B-sparse-hccl.sh, tests/test_sparse_hccl.py, tests/test_qwen3_30B_A3B_sparse_hccl_npu.py Wiring now matches vllm-project#480 exactly (sparse is a delta-mode transport, not a second full-mode carrier): - --update-weight-transport gains sparse_hccl, plus --update-weight-delta-batch-diff, --update-weight-delta-batch-gather and --update-weight-delta-verify-every - delta + sparse_hccl selects UpdateWeightFromSparseHCCL; delta stays disk|sparse_hccl - rollout engines get weight_transfer_config={"backend":"sparse_hccl"} when mode is delta and transport is sparse_hccl - update_weight_from_distributed.py is left untouched, so the dense nccl path is unchanged Removed: the hand-written sparse_diff_source.py and its unit test, plus the full-mode dispatch/transport edits, which vllm-project#480 supersedes. Signed-off-by: A5 sync <a5-sync@local>
ea3f6e7 to
f683563
Compare
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
788435f to
3b609cf
Compare
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
…erage Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Signed-off-by: wangx700 <wangxin700@huawei.com>
Add sparse HCCL weight synchronization between Megatron training and vLLM-Ascend rollout, plus an end-to-end comparison against a freshly loaded checkpoint.
Interface flow
Pause generation → start update → Bridge export or shard diff → ordered trainer-rank gather → payload preparation → send_weight_chunk → HCCL broadcast and checkpoint loader → finish update → resume generation.
The first synchronization sends complete checkpoint coordinates and values. Later synchronizations send only changed positions. Both use Bridge conversion and unpacked sparse patches. Inference uses PP=1; the six-NPU configuration trains with TP2/PP2/EP2 and rolls out with TP2/PP1/EP2.
Implementation
Simplify
tests/test_sparse_hccl.pyfrom 22 functions / 37 parameterized cases to 19 functions / 35 cases. Merge sender/non-sender seeding and parallel-config rejection cases, share updater setup, and remove redundant one-record batching and optimization-specific assertions. Preserve the four-rank full-export reconstruction, 12 publication/failure combinations and 20 gather combinations. The non-sender seed case now drains a nonempty export iterator; seed reconstruction also checks zero values against a NaN-initialized destination.Align the dependency sparse engine with vLLM-Ascend PR18915 at
841dcfc1c: checkpoint loader views and validation live inside the sparse engine. No sparse changes remain inrouted_experts.py. Keep the older pinned dependency's supported HCCL initialization API instead of importing the newerhccl_commonmodule.Synchronize trainer failure state after every nonempty gather queue flush, before any rank enters its next gather. Preserve the original sender exception on rank zero and propagate a synchronized failure on peers. Existing recovery distinguishes validation failures before transmission from potentially partial sends, which keep generation paused. Add 12 distributed regression cases covering immediate/residual batches, gathered/replicated rows, success, validation failures and sender failures.
Document the sparse export prerequisite: Megatron-Bridge is absent from the standard NPU installation. The historical A5 run used v0.3.0 at
21b02e0cfb2f8ff907e0d8baee0c5205876c6812. Its Transformers <5 requirement differs from the measured A5 Transformers 5.17.0 stack; that combination needs environment-specific validation.Group shared incremental synchronization helpers under
vime/backends/megatron_utils/delta_sync/:hf_weight_iterator_bridge.py,megatron_delta_export.pyandsparse_gather.py. Keep the transport-specific updater inupdate_weight/update_weight_from_sparse_hccl.py. Update its imports and test imports without changing helper implementations or updater/test execution logic.McoreParamExportdirectly stores gather routing;delta_spec.pyis removed.Remove sparse updater metrics, per-phase timers, profiling contexts and success-statistics logs. Keep the shared pop_metrics() interface returning an empty dictionary.
Remove the unused verification flag, shape/placement bookkeeping, redundant slot cache and ignored iterator arguments.
Use one bounded batched diff implementation for both batch size 1 and larger batches. Keep bitwise comparison, snapshot refresh and Bridge conversion.
Remove added dependency profiling and unused loader extension hooks and their dedicated tests. The existing checkpoint loader and Ascend layout adaptation remain.
Keep numeric payload validation, inference PP/PCP checks and recovery after failures. Ordered indices retain linear duplicate checking; unordered indices retain the sorting fallback.
Keep sparse additions focused on backend registration, HCCL communicator cleanup and checkpoint loader views, with relevant unit tests. Preserve all pre-existing Ascend compatibility patch sections from the PR base, including IPC, packed transfer, worker/model runner, KV-cache, disk reload, device and convolution fixes; these are baseline behavior and are not sparse HCCL changes. Retain the baseline full HCCL trainer. Remove only the newly added standalone example, dependency-side five-NPU end-to-end test and its registration helpers. The VIME end-to-end inference comparison remains.
Keep the standard six-NPU launcher and enable sparse synchronization using --update-weight-mode delta and --update-weight-transport sparse_hccl.
End-to-end inference comparison
tests/test_qwen3_30B_A3B_sparse_hccl_npu.py now:
Use a fresh result directory with room for a complete BF16 checkpoint (about 61 GB). Artifacts include baseline.json, sparse-inference.json, checkpoint-inference.json and comparison.json. The comparison records per-field equality and maximum absolute logprob error; strict success requires zero error. The test observes successful patch publication only to require nonempty updates; it does not collect timing metrics. A one-prompt match only establishes consistency for that input.
Runtime prerequisites
Sparse export requires Megatron-Bridge. The standard NPU installation does not include it. The validated fixed version is v0.3.0 at
21b02e0cfb2f8ff907e0d8baee0c5205876c6812:--no-depspreserves the installed NPU training/serving stack. Bridge v0.3.0 declares Transformers <5; the historical A5 validation used Transformers 5.17.0. That measured combination does not establish general dependency compatibility. Bridge must be provided by the training environment.Current measured unpacked baseline
Qwen3-30B-A3B, A5, six NPUs: training TP2/PP2/EP2 and inference TP2/PP1/EP2. Both historical jobs completed successfully on 2026-10-27.
Table note: seconds are complete update_weights wall-clock calls, including preparation, transfer and inference application. Full transmits all weights each round; sparse sends the listed changed-element events. The denominator is 30532122624 seed elements. Repeated coordinates across versions count again. Payload includes int32 indices and BF16 values, excluding protocol overhead. Steady averages from these rounded Timer values are approximately 52.57 s and 35.10 s; sparse saves about 33.2% against unpacked full. These measurements precede this revision and do not establish a speedup from the new validation optimization.
Validation
Current head:
156f18fd85868ad55471a48f6559f36dcb3fea88.Real trainer-side regression on 192.168.13.188
Container
cjy-vime-npu-1023, isolated directory/home/w00899129/pr492-18915-align-188.VupM0o, NPUs8,9,10,11. Installed Bridge v0.3.0 at21b02e0cfb2f8ff907e0d8baee0c5205876c6812into an isolated target without dependencies; Megatron source was pinned at1dcf0dafa884ad52ffb243625717a3471643e087.All 37 tests passed, exit code 0, with no skips. The distributed test used actual training TP2/PP2/EP2/ETP1, real Bridge conversion and real HCCL gathering. Sparse reconstruction of all 45 HF tensors was bitwise identical to an independent full export, including BF16/FP32 and PP placeholders. The 12 failure/publication cases ran on four actual trainer ranks with controlled export/sender failures. The 20 gather cases cover empty/unequal/noncontiguous/split/reused buffers. These subcases belong to the 37 tests and are not additional pytest test counts. 105.33 seconds is complete pytest wall time, not weight-update latency.
The 37-test trainer result above is historical, from the original
71fa4d4fsnapshot. Subsequent changes move the three unchanged helper modules intomegatron_utils/delta_sync/and simplify the test suite to 19 functions / 35 parameterized cases. The revised suite has not been rerun on remote hardware. Local pre-commit and parsing passed; all five merged unsupported parallel configurations were checked against the actual connection guard and rejected before setup. Historical results are not presented as a pass of this revised suite.Real receiver regression on the pinned serving pair
Container
cjy-vllm-acend-1019, same isolated directory. Applied both VIME dependency patches to clean exports of vLLMe6bfe03ad73a3330cb427885aa90d97a12e1c704and vLLM-Ascendfd815467c221ee600137f6bdd53fe354d5e7c999:8,9,10). Every worker's complete parameter hashes and greedy generated token IDs matched native dense loading. Each case applied 37 patch records, including a repeated coordinate update. This is a small synthetic model, not pretrained-model accuracy or performance validation.1,4,5failed during worker initialization after other jobs occupied the selected memory; that failure log is retained separately.verified-results.jsonrecords the receiver results and input hashes. The earlier two-rank publication probe also passed all 12 cases; the full four-rank test above supersedes that probe for trainer publication coverage.Raw logs:
trainer-bridge.log,pinned-ut-final.log,pinned-e2e-free.log, their exit-code files, source manifests and both receivervalidation.jsonfiles under the isolated directory above.Repository checks
Full
pre-commit run --all-files --show-diff-on-failurepassed after fixing two isort imports. The final source matches the checked files; the production implementation is unchanged by the formatting fix.NPU CI steps retain the environment update and test launch commands; automatic Bridge installation has been removed.
The combined Ascend patch passed actual clean-index application on
fd815467c; all 13 affected Python files parse. All 12 pre-existing compatibility patch sections remain unchanged from the preceding functional head, including IPC and worker fixes.All PR commits contain sign-offs; GitHub DCO passed after the historical sign-off and email cleanup. Added missing sign-offs to 23 historical commits (16 wangx700 and 7 A5 sync). With the author's confirmation, the 7 A5 sync commits retain their author name and use the existing valid email
wangxin700@huawei.cominstead ofa5-sync@local. Author dates and every code tree remain unchanged by the metadata rewrite.Remaining acceptance limits