Java to Rust Migration
Migrate contracts and observable behavior, not Java syntax. Preserve the Java project's public concepts and source traceability while selecting Rust-native ownership, error, concurrency, async, serialization, and framework mechanisms.
Mandatory migration layout
- Derive the Rust directory from the Java package after the declared package root; preserve meaningful nested packages and never flatten, cross-place, or double-nest them.
- Convert the Java object name to acronym-aware
snake_case.rs; keep the Rust type in PascalCase and do not add suffixes such as _trait.
- Keep one Java object as one Rust object boundary. Rust defines no universal file-length limit: treat up to 500 physical lines as normal, review 501–800 lines for cohesion, and block authored
.rs files above 800 lines.
- Split only when a file mixes responsibilities. Retain one primary object file and use subordinate files for coherent implementation families without introducing a second migrated object; record every split or reviewed exception.
- Keep
lib.rs and mod.rs to declarations and re-exports. Update parent modules after moves and qualify ambiguous external re-exports with ::.
- Keep focused private-behavior unit tests in
#[cfg(test)] modules when useful. Put public-boundary, cross-module, differential, host, and whole-project tests under tests/ or a non-published <project>-test package; keep source fixtures under <project>-test/tests/fixtures/.
Read Directory path alignment and Layout and governance, then run the layout audit after moves.
Scope and Routing
Use this skill for full-project migrations, one Maven/Gradle module, parity audits, migration planning, or continuation of an existing Rust port.
This is the Rust adapter of the cross-language migration profile. Route crate/layout/API, dependency, macro, and domain mechanics to the corresponding Rust skills. Route verification to rust-java-migration-testing plus relevant test skills.
Do not modify migration code when the user requested only an audit, plan, or documentation. A plan-only or read-only request does not authorize running a write-producing document scaffolder: return the proposed four-document content in the response, use --dry-run, or write only to a user-approved destination. Do not broaden a module migration into a repository rewrite without authorization.
Required Inputs
Resolve or explicitly mark unknown:
- Java repository path, baseline commit/tag, build tool, JDK, and module scope.
- Exact Java module package root used for path mapping; do not pass only a repository or
src/main/java root and guess which segments to strip.
- Rust repository path, baseline commit, toolchain/MSRV, workspace, and target platforms.
- Target-product topology inputs: independently published Rust units, dependency/feature/target/proc-macro/FFI boundaries, expected crate count, package families, root noise, other languages, and established paths.
- Compatibility goal: source-shape parity, public API parity, behavior parity, or production replacement.
- Dependency policy: license, MSRV, supported targets, unsafe policy, advisory policy, maintenance horizon, and acceptable transitive cost.
- Component-candidate sources and their observation date; distinguish team policy, researched candidates, declared dependencies, and verified adoption.
- Explicit exceptions, blocked external projects, unsupported JVM-only features, and completion deadline.
- Required host applications, real scripts, test data, concurrency model, load profile, and rollback mechanism.
- Existing migration documents and their authority; identify the single current four-document set before merging historical material.
- Complete source test roots/runner configuration, including every concrete test case, disabled test, fixture, script, corpus, golden file, resource, and data file. The source repository defines the denominator; do not narrow it to fit Rust.
Never silently infer that the newest branch, a generated manifest, or an API registration list is the behavioral baseline.
Workflow
Treat one declared Java source module and its Rust target crate/module as the default migration batch. A user-authorized multi-module scope may be one batch, but freeze its boundary before implementation. Apply: freeze scope/contracts → implement the batch → freeze → audit → unified verification.
Dependency-ordered editing inside the implementation batch is allowed. Per-object completion loops are not.
1. Freeze baselines and inspect repository state
Record both repository SHAs, dirty worktrees, Java/Rust toolchains, module manifests, enabled features, and generated-code boundaries. Preserve existing Rust work and unrelated changes.
Verify the Rust toolchain satisfies the workspace MSRV: an older default rustc fails with rustc X is not supported by the following packages — run gates via rustup run <ver> cargo ..., never silently lower rust-version.
If a repository contains .codegraph/, use CodeGraph before text search or file-by-file reading:
- Survey module/package/crate architecture.
- Query representative public types and overloaded methods.
- Trace high-value call chains across factories, registries, interceptors, serializers, persistence, networking, and concurrency.
- Query the Rust counterparts and their callers/tests.
- Refresh or re-query the module inventory before implementation if the index reports staleness.
If no index exists, do not initialize one without authorization. Use language-aware tooling or targeted source inspection and disclose the weaker evidence.
Read CodeGraph parity audit for query patterns and inventory rules.
Read Case-study lessons when designing a large utility-library migration or an annotation/macro split.
1.5. Derive Rust crate boundaries and workspace topology
Do not map Maven/Gradle modules one-to-one to Cargo packages. Derive Rust packages from independent publishing/reuse, dependency/feature/target isolation, proc-macro or FFI constraints, and distinct lifecycles; source modules remain traceability scopes.
Select placement with rust-workspace: small cohesive results are normally root-flat; real adapter/binding/example/test families support a hybrid; large, root-heavy, or multi-language repositories may use crates/. Counts are review triggers, not laws. Record the source-module-to-crate mapping, chosen topology, rejected alternatives, and compatibility plan in the roadmap. See Layout and governance.
2. Build inventories before implementation
Create separate machine-readable or tabular inventories for:
- Java Maven/Gradle modules and Rust crates.
- The source-module-to-crate mapping and why root-flat, hybrid, or contained/grouped paths fit this project.
- Java packages and Rust module directories.
- Classes, interfaces, enums, records, annotations, exceptions, and relevant inner types.
- For every object, the deterministic Rust path after removing the organization/module package root and retaining the final two remaining segments (or one/zero when fewer remain).
- Public/protected constructors and methods, including every overload.
- Parameter names, order, generic bounds, nullability, defaults, varargs, checked exceptions, and return contracts.
- Existing object, constructor, method, generic/value parameter, return, exception, metadata-tag, and semantic inline comments, with source anchors.
- Examples, tests, fixtures, scripts, configuration, resources, service descriptors, and docs.
- A source-test case manifest and asset manifest; record every concrete case and asset path/hash before copying resources byte-for-byte into Rust.
- A non-published
<project>-test package owning project-level source replay, cross-component paths, and differential acceptance.
- Call paths and externally observable side effects.
Exclude package-info, generated sources, BOMs, aggregators, test support, facades, and Rust-only infrastructure only through explicit categories. Do not hide them by changing the denominator.
Freeze the inventory as the batch manifest before production edits. Cover the complete denominator, dependency order, shared mechanisms, component decisions, test disposition, and approved exceptions; do not discover scope object-by-object.
Resolve SKILL_DIR from this SKILL.md; never assume a fixed install path. Run commands from the Rust migration root and prefer repository-relative inputs/artifacts.
Run the static Rust layout audit as an early signal:
python3 "$SKILL_DIR/scripts/audit_migration_layout.py" \
--java-package-root ../java-project/source-module/src/main/java/org/example/module \
--rust-root . \
--retain-segments 2 \
--require-source-comments \
--fail-on-warning
The script calculates expected paths and distinguishes missing from misplaced
objects. It also detects non-snake-case paths, multi-object files, facade
definitions, wildcard imports, stub macros/panics, empty function bodies, and
missing Chinese source comments. Record an approved 501–800-line cohesion review
with repeated --reviewed-large-file path/to/file.rs; this never exempts a file
above 800 lines. Any strict blocker keeps migration completion blocked; a clean
scan still does not prove Java/Rust semantic parity.
3. Create four documents for every source module
When documentation writes are authorized, generate a documentation directory for each Java module before implementation:
python3 "$SKILL_DIR/scripts/scaffold_migration_docs.py" \
--module source-module \
--java-root ../java-project/source-module \
--java-package-root ../java-project/source-module/src/main/java/org/example/module \
--rust-root <selected-target-crate-or-workspace> \
--output-dir docs/source-module \
--java-baseline <sha-or-tag> \
--rust-baseline <sha> \
--retain-segments 2
The command creates:
迁移路线图.md — scope, baselines, phases, dependencies, risks, and evidence gates.
对象级对照表.md — every Java object and its Rust file/type/status.
语义迁移对照表.md — every behavior family and its Rust-native implementation.
对象名称一致性检查.md — counts, missing/extra/merged objects, names, methods, parameters, and logic gaps.
Populate every placeholder from source evidence. A generated template is
DRAFT, not evidence and never completion. Keep documents synchronized with
code in the same change. Templates:
- Migration roadmap
- Object mapping
- Semantic mapping
- Name consistency audit
Every one of the four documents must be independently detailed and must contain
the module's current migration contract: source/Rust SHAs, exact object
denominator, target root, retain_segments = 2, status snapshot, strict
completion rules, and that document's responsibility. Reject a title-only,
count-only, or placeholder-only document. As an anti-summary floor, require at
least three substantive level-2 sections plus an evidence table or task matrix;
use a repository-configured size floor (45 nonblank lines by default) while
allowing a proportionally smaller generated object table for a genuinely tiny
module.
Every document must show separate Java and Rust baselines, its last-audited date,
and a document status. Every migrated/verified row needs an evidence anchor:
source file or symbol, target file or symbol, test/oracle, exact command, and
artifact where applicable. During implementation, do not upgrade rows one at a
time. After the batch freeze, cross-check all four documents against the current
Rust SHA and update statuses in one consolidated pass. A later count table must
not silently contradict a technical-requirements document or an earlier semantic
gap.
Keep exactly one current four-document set at the module root. Do not leave
*-历史详细版.md or a second history/**/<current-name>.md beside it. Merge
useful old package grouping, design context, and decision history into a clearly
delimited “历史设计附录” in the corresponding current document. The generated
current-fact region must remain first and regeneration must preserve the
appendix. Old counts, paths, statuses, tests, and completion marks never override
current facts.
Treat scaffold --force as destructive and use it only for a disposable,
untouched DRAFT; never use it to merge or refresh a populated current
document. Merge historical details into the current document in place and
preserve both its generated fact region and existing appendix.
4. Classify every object honestly
Use these object states consistently. Keep verification levels (V0–V7)
separate; do not invent a friendlier state or translate a test result directly
into an object state.
| State |
Meaning |
MISSING |
Expected Rust object file does not exist |
MISPLACED |
Same-name file/type exists but not at the deterministic expected path |
STUB |
Shape or placeholder exists but real behavior is absent |
PARTIAL |
Real behavior exists but methods, callbacks, errors, ordering, lifecycle, or integration semantics are incomplete |
UNVERIFIED |
File/logic exists but source comments, object boundary, or semantic test evidence is insufficient |
IMPLEMENTED |
Expected path, one-object boundary, real complete logic, Chinese source semantics, and current semantic tests all exist |
DEPENDENCY_REUSED |
A pinned dependency provides the exact capability; crate/version or commit, upstream symbol, adapter, and local integration test are recorded |
PLATFORM_NA |
The capability is genuinely JVM/bytecode/class-loader/platform-only and explicit evidence records why no Rust object applies |
RUST_EXTENSION |
Intentional Rust-only capability, excluded from Java parity numerator |
Only IMPLEMENTED, DEPENDENCY_REUSED, and PLATFORM_NA count as handled
source objects. MISSING, MISPLACED, STUB, PARTIAL, and UNVERIFIED are
incomplete. RUST_EXTENSION never enters the Java denominator.
Allow a planned placeholder only when the user explicitly approves it. Record
the blocker in the roadmap, but keep each affected object in its factual
MISSING or STUB state. A blocker is metadata, not a completion-like object
state.
Never upgrade from MISSING merely because an object name appears in a manifest,
facade, lib.rs, mod.rs, re-export, generated registry, or compatibility
module. Never upgrade from UNVERIFIED merely because cargo test is green.
5. Decide component replacements from contracts
Do not map framework names directly. For every external Java component or framework subsystem:
The Java source module remains authoritative for object names, package
structure, and public contracts. A Rust dependency is only an implementation
reuse boundary. Do not restructure the migration around the dependency's file
tree and do not copy dependency-owned implementations into local files merely
to improve parity counts. For AOP-like work, for example, Spring defines the
Advice/Interceptor/Advisor object inventory while an aspect crate may satisfy
specific runtime symbols through DEPENDENCY_REUSED.
- Extract the behavior contract: API shape, wire/storage format, ordering, failure taxonomy, lifecycle, transactions, concurrency, cancellation, backpressure, security, observability, and deployment assumptions.
- Choose a replacement shape: standard library, direct crate, wrapped crate, trait plus adapters, explicit registry/SPI, compile-time macro/code generation, application-host responsibility, or proven
PLATFORM_NA.
- Check the common mapping table and candidate catalog as discovery starting points, never as automatic approval.
- When no verified mapping fits, generate several English capability/protocol/constraint queries, search crates.io and companion primary sources, and shortlist five to ten candidates across std, direct crate, wrapper, trait/adapters, code generation, host responsibility, and exclusion shapes.
- Route crates.io metadata collection and ecosystem-health comparison to
rust-crate-discovery when available. Apply migration-specific contract and compatibility gates here; its numeric health score does not select the replacement.
- Reject candidates that fail a required contract, license, MSRV/target, runtime/blocking, protocol, security, maintenance/ownership, or dependency-graph constraint before scoring.
- Compare viable candidates using semantic fit, maintenance, adoption, docs/tests, project compatibility, security/supply chain, maturity, cost, and exit strategy. Interpret downloads, reverse dependencies, stars, release recency, and commits as contextual signals, not proof.
- Spike the highest-risk semantic path for the top candidates before committing the architecture.
- Record search queries and date, ownership, version/features, per-dimension evidence/confidence, rejected alternatives, escape hatch, and rollback plan.
- Promote an object to
DEPENDENCY_REUSED only when the exact upstream symbol,
pinned dependency evidence, adapter boundary, and local integration test are
all recorded. “The ecosystem has it” or “semantically similar” remains
UNVERIFIED.
For multiple target frameworks, define a framework-neutral contract and thin adapters, then run one shared conformance suite against every adapter. Keep runtime traits/types separate from thin procedural macros and generated code.
Read Component replacement decision SOP, crate replacement discovery and evaluation, and Component candidate catalog before choosing or approving a third-party replacement. The catalog is discovery input, never an approval list; re-verify release, maintenance, license, MSRV, targets, advisories, unsafe/build-script surface, and required contracts at decision time.
6. Complete the declared batch in one semantic implementation pass
Read Layout and migration rules,
Directory path alignment patterns and error catalog,
and Semantic mappings before changing code. Then
execute the entire frozen batch without object-level acceptance pauses:
- Establish the target module tree, shared errors, traits, registries, adapters,
serialization rules, concurrency model, and dependency boundaries once.
- Implement every mapped Java object and operation in dependency order. Keep
exactly one primary
.rs file per Java object and real logic in the
corresponding object or explicit collaborator files.
- Copy and translate JavaDoc semantics into Chinese Rust doc comments across
the batch. Migrate every existing object comment, constructor/method comment,
generic and value
@param, @return, @throws, @since, @deprecated,
relevant @see, and semantic inline comment without omission. Preserve the
parameter-specific contracts. Keep Java-to-Rust name, signature, and exception
mappings in the four migration documents; keep generated Rust documentation
Rust-native.
- Implement all mapped overload variants, examples, fixtures, source-test
counterparts, Rust-specific obligations, and risk-driven tests as batch
artifacts, but do not execute validation yet. Preserve 100% of source test
inputs, assertions, error expectations, state, side effects, and cleanup.
Copy source test files/data/resources without editing them; put any
Rust-specific derivatives in separate files.
- Maintain one deferred-issues ledger. Continue through local uncertainties;
pause only for a blocker that changes the frozen public contract,
architecture, dependency policy, or authorized scope.
- When every non-exempt manifest row has real implementation, freeze the Rust
batch. Only then update the four documents in bulk and enter audit.
During this pass, do not run cargo check, tests, Clippy, coverage,
differential comparison, per-object CodeGraph re-queries, or per-object
completion reviews. Do not report an object as accepted merely because its file
was edited. Recovery commits are allowed, but they are not verification gates.
Read Comment migration contract and example
before migrating documentation. Treat missing source comments as migration gaps,
not optional cleanup.
7. Preserve naming and overload intent
- Use
snake_case for Rust directories, files, methods, and parameters.
- Use
PascalCase for Rust types.
- Map
loadOrCreateAgentState(slotKey) to load_or_create_agent_state(slot_key).
- Remove the organization and declared source-module package root, then retain
exactly the final two remaining package segments. Retain one when only one
remains and place root-package objects at the crate root. Example:
factory/xml/support/Foo.java → xml/support/foo.rs;
propertyeditors/PatternEditor.java → propertyeditors/pattern_editor.rs.
- Keep
lib.rs and mod.rs as declarations and re-exports only.
- Keep one Java class/interface/enum/record per Rust file; an inner builder tightly owned by the primary type may remain with it.
- Treat 500 physical lines as a cohesion-review threshold and 800 as the authored-file blocker. Split by responsibility rather than line ranges; no subordinate file may introduce another migrated object.
- Enable
clippy::too_many_lines as a function/method review signal at its 100-line default; refactor long routines when they combine distinct responsibilities.
- Use Rust's idiomatic test organization: colocate focused unit tests in
#[cfg(test)] modules, and place public-boundary, cross-module, differential, host, and whole-project tests in tests/ or a test/testkit package.
- Record every intentional rename in both object and name-consistency documents.
Rust has no method overloading. Keep one canonical snake_case name only when the signatures have one semantic operation. Give additional variants stable semantic suffixes such as _with_charset, _into, or _from_reader; record the exact Java signature mapped to each Rust function. Never collapse overloads that differ in defaults, validation, side effects, or error behavior.
Apply the local rust-api-design conventions to every migrated public Rust
surface. Do not mechanically translate JavaBean accessors: prefer name() over
get_name() (except genuine lookup operations), set_name(value) for controlled
mutation, name_mut() only when it cannot bypass invariants,
into_name()/into_inner() for ownership transfer, semantic boolean predicates,
and chainable builders. Use as_/to_/into_, From/TryFrom/AsRef and
IntoIterator by their Rust meanings; do not use Deref to emulate Java
inheritance. Expose fields directly only when invariants and API evolution permit
it. Preserve validation, visibility, side effects, exceptions, synchronization,
and lazy-computation behavior.
When a script, expression engine, serializer, reflection facade, or other
compatibility surface exposes Java property semantics, keep the Rust API
idiomatic and implement the old field/getter/setter behavior in an explicit
registry or member resolver. Record this relationship as mapping form
ADAPTED; this is orthogonal to completion status and still requires
IMPLEMENTED, UNVERIFIED, or another factual state.
Read Rust API and JavaBean property adaptation
before migrating getters, setters, builders, or script-visible properties.
8. Translate mechanisms, not frameworks literally
Use this table as a common starting point, then verify the exact contract and
current crate evidence:
| Java responsibility |
Rust starting point |
| Jackson JSON annotations/modules |
serde, serde_json, project-owned custom serializers |
| Jackson XML / JAXB-style XML |
quick-xml plus explicit namespace, attribute, mixed-content, and ordering logic |
null, checked exceptions |
Option<T>; typed thiserror enums and Result |
| SLF4J/Logback/MDC |
tracing, tracing-subscriber, explicit field/context propagation and redaction |
synchronized / ConcurrentHashMap |
ownership first; then std Mutex/RwLock or DashMap when the access pattern warrants it |
CompletableFuture, scheduled executors |
async futures, supervised Tokio tasks, cancellation tokens, timers/intervals; select a scheduler crate only for richer contracts |
Reactor Mono<T> / Flux<T> |
async fn -> Result<T, E>; bounded Stream<Item = Result<T, E>> |
| OkHttp / Apache HttpClient |
reqwest for high-level clients; Hyper for protocol-level control; verify TLS, proxy, pool, redirect, retry, and streaming semantics |
| Spring MVC/WebFlux / JAX-RS |
framework-neutral core plus approved Axum, Actix Web, Poem, or other thin host adapters |
| JDBC/JPA/MyBatis |
SQLx, Diesel, SeaORM, RBatis, or another verified data layer selected by query, mapping, transaction, migration, and runtime contracts |
| Caffeine/Guava cache |
Moka or a project-owned cache; verify eviction, TTL/TTI, loading, invalidation, and concurrency |
| Jedis/Lettuce |
redis; verify cluster/sentinel, reconnect, pipeline/transaction, TLS, and async behavior |
| Kafka/RabbitMQ/Pulsar/NATS/MQTT |
protocol-specific client such as rdkafka, Lapin, pulsar, async-nats, or rumqttc; require real-broker semantics and recovery tests |
| Protobuf / gRPC |
Prost; Tonic plus Prost for gRPC |
| Bean Validation |
validator or project-owned validation, kept separate from framework extractors |
java.time, UUID/ULID, BigDecimal, regex |
time/chrono, uuid/ulid, rust_decimal/bigdecimal, regex; choose representations and compatibility before crate preference |
.properties, YAML, TOML, configuration binding |
java-properties, serde_yaml_ng, toml, or a verified configuration crate plus project-owned precedence/profile rules |
| Apache Commons/Hutool general utilities |
std first, then focused crates such as url, bytes, regex, base64, or hex; do not seek one umbrella crate by name |
| Micrometer/OpenTelemetry/Prometheus |
metrics, OpenTelemetry ecosystem, Prometheus exporters, and tracing integration; preserve names, labels, cardinality, context, and shutdown |
| JavaMail |
lettre; verify MIME, attachment, TLS/authentication, retry, and delivery reporting |
| JWT/passwords/general crypto |
jsonwebtoken, argon2, and focused RustCrypto crates; select algorithms/formats from the security contract, never from convenience alone |
| Groovy/Nashorn/embedded scripts |
rhai, boa_engine, mlua, PyO3, or Wasmtime according to language, sandbox, resource-limit, threading, and packaging requirements |
| Apache POI/document formats |
format-specific crates such as rust_xlsxwriter, calamine, docx-rs, printpdf, or lopdf; validate actual Office/PDF fixtures and unsupported features |
| ServiceLoader/SPI |
explicit registry first; inventory only when link-time registration is required |
| Spring IoC/AOP/runtime annotations |
constructors/builders, traits, middleware, registries, wrappers; use macros only for compile-time behavior |
| FreeMarker / Velocity / compile-time views |
Tera / Handlebars; Askama for compile-time templates; maud for Rust-native markup |
| Lombok data boilerplate |
standard derives plus invariant-preserving APIs/builders; evaluate lombok-macros only against the generated API contract |
| JUnit/Testcontainers |
Rust unit/integration tests; testcontainers for disposable real dependencies |
| JNI/manual Swift/Kotlin/Python bindings |
UniFFI when its supported type/error/async model fits; shipping and packaging remain separate work |
Prefer composition of mature Rust crates over recreating a Java all-in-one implementation, but retain the source project's observable facade when compatibility requires it.
9. Extract annotation behavior behind a stable macro boundary
Do not place procedural macro entry points in a normal runtime crate. Use:
project-core # runtime traits, types, errors, and generated-code contract
project-macros # thin proc-macro entry points and syntax parsing
project-web-* # framework adapters that may re-export approved macros
Use -derive only for a derive-only public surface; use -macros for attribute/function-like or mixed macros, unless the existing crate family has a deliberate established spelling. Keep generated code dependent on public runtime APIs, not proc-macro internals. Test expansion success, compile failures, generics, visibility, renamed dependencies, and each framework re-export.
Java runtime annotations do not automatically become Rust macros. Use middleware, traits, registries, or explicit builders when runtime state and dynamic dispatch own the behavior.
10. Audit once, then verify the complete batch
After the implementation freeze, execute the applicable ladder for the whole
declared batch:
- Run one consolidated CodeGraph/static parity audit over all objects, files,
exact signatures, parameters, overloads, call paths, dynamic boundaries,
examples, tests, docs, and placeholders. Compare the complete Java comment
inventory with Rust object, method, parameter, return, error, metadata, and
inline comments. Reconcile all four documents in one pass.
- Run Rust formatting, check, unit, doc, integration, Clippy, feature, target,
and platform gates as one unified engineering suite.
- Run every ported/mirrored Java contract test, clearly labeled as
non-differential evidence.
- Run the complete pinned Java suite and the complete Rust lossless-port suite,
then run the complete Java golden exporter or live Java/Rust differential
suite over every concrete source case. Require both suites to pass and every
case to report
MATCH; zero mismatches, harness failures, and not-run cases.
Execute this from the dedicated <project>-test package; local
production-crate tests remain subsystem evidence only.
- Replay the complete set of real user scripts and examples against both
implementations.
- Run concurrency acceptance for ordering, cancellation, backpressure, races,
shutdown, and Loom/model properties where useful.
- Run load/stability tests for throughput, latency percentiles, memory,
handles/tasks, reconnects, and soak.
- Run security property tests, malformed-input suites,
cargo-fuzz, unsafe
review, dependency advisories, and secret-redaction checks.
- Run real business-host integration with databases, networks, files,
frameworks, and deployment topology.
- Run the gray rollout and rollback drill with recorded recovery time and
state compatibility.
When a gate fails, group failures by shared subsystem or root cause, repair the
batch, and rerun the affected consolidated gate plus downstream invalidated
gates. Never fall back to migrate-compare-test one object at a time.
Read Verification and acceptance for evidence design and use rust-java-migration-testing for the three-ledger testing SOP. Before repairing a non-compiling or warning-heavy workspace, read Compile drift and migration cleanup: dependency/version drift, MSRV, crate-root re-export chain breaks, duplicate cross-crate types, Java-mirror naming/scaffolding norms, and the zero-warning check workflow (default + --all-features, --keep-going layered errors, per-crate attribution, tests after cleanup).
11. Report completion without inflating coverage
Report structural, implementation, behavioral, test, integration, and production
readiness separately. For behavior, distinguish mirrored contracts, golden
differential, live differential, and approved equivalent oracles; for tests,
separate losslessly migrated source tests from Rust-native additions.
Include exact commands, SHAs, test counts, failures, exceptions, and unverified boundaries. Never call a migration complete because code compiles or a parity manifest reaches 100%.
Red Lines
- Do not define many migrated objects in
lib.rs, mod.rs, or compat.rs.
- Do not delegate every object to one
compat.rs implementation.
- Do not use empty bodies,
todo!(), or unimplemented!() as completed migration.
- Do not delete or simplify working migrated behavior to make counts align.
- Do not use wildcard imports in production migration code.
- Do not silently merge several Java objects into one Rust file.
- Do not keep an authored
.rs file above 800 physical lines; review every file above 500 and split it when cohesion is weak.
- Do not mechanically compress code, remove useful comments, or split arbitrary line ranges merely to satisfy a size gate.
- Do not embed integration, differential, host, load, or whole-project acceptance suites in production modules; inline
#[cfg(test)] unit tests remain valid for focused module-private behavior.
- Do not replace overloaded behavior with one lossy convenience function.
- Do not create
get_* methods solely to mirror JavaBean spelling when an idiomatic Rust method plus an explicit compatibility adapter preserves the contract.
- Do not treat an idiomatic Rust getter/setter as sufficient when scripts or dynamic member access still require Java field/getter/setter resolution.
- Do not call a declared dependency, successful compile, or isolated POC a verified component replacement.
- Do not use a replacement dependency's package/file layout as the target object inventory; source Java objects and the deterministic path rule remain authoritative.
- Do not mark a semantically similar dependency as
DEPENDENCY_REUSED without pinned crate/commit, exact source symbol, adapter evidence, and local integration tests.
- Do not use
PLATFORM_NA for work that is merely difficult or missing; require JVM/bytecode/class-loader/platform-specific evidence.
- Do not promote a component copied from a research list or local convention document to “selected” without current hard-filter and contract evidence.
- Do not call a Rust test copied from a Java test a differential test unless both implementations or Java-produced golden artifacts participate.
- Do not declare source-test parity from dispositions alone. Every source case needs a lossless target and golden/live
MATCH; MISSING, BLOCKED, and NOT_APPLICABLE block completion.
- Do not modify copied source fixtures, scripts, corpora, golden files, or test data in place. Verify source/target SHA-256 and keep generated derivatives separate.
- Do not treat independently green suites or equal test totals as parity; compare per-case outputs, errors, state, side effects, and cleanup.
- Do not substitute production/binding-crate local tests for the non-published
<project>-test whole-project acceptance package.
- Do not copy Maven/Gradle modules one-to-one into Cargo packages without a Rust publishing, dependency, target, macro/FFI, or lifecycle reason.
- Do not force every workspace into
crates/ or root-flat; record topology from product scale, families, repository noise, and compatibility.
- Do not mark a row behavior-verified from file counts, parser acceptance, generic
is_ok()/is_err(), or “at least one test per object”.
- Do not let the four migration documents carry different baselines or contradictory completion states.
- Do not keep a current document and a
-历史详细版/nested duplicate; merge useful history after the generated fact region.
- Do not replace the generated current-fact region or let regeneration discard the merged appendix.
- Do not claim real testing when only mocks, compilation, or static inspection ran.
- Do not edit reference source repositories while extracting patterns.
- Do not alternate migration, comparison, and testing for each object, file, or method.
- Do not run object-scoped acceptance during implementation; finish the frozen batch before consolidated audit and unified verification.
- Do not convert recovery commits or local edit milestones into completion checkpoints.
- Do not omit an existing Java object, constructor, method, parameter, return, exception, lifecycle, thread-safety, deprecation, or semantic inline comment.
- Do not replace source documentation with generic prose or claim comment parity from
cargo doc alone.
- Do not write
对应 Java in parameter, return, error-variant, field, or inline comments. Limit optional anchors to Rust type and constructor/method docs; keep detailed correspondence in the four documents.
- Do not rename Java-mirror SCREAMING_SNAKE enum variants or delete Java-mirror scaffolding types to silence
non_camel_case_types/dead_code; use #[allow(...)] + comment and keep the Java inventory intact.
- Do not declare a workspace clean from the default-features gate alone;
--all-features must also reach zero warnings, and do not silently lower rust-version to match an old local rustc — run the pinned toolchain via rustup run <ver> cargo ....
- Do not edit a path dependency while cleaning a dependent crate; attribute each warning to its owning crate's
--> path first.
- Do not fix "all errors" from one
--keep-going output; errors surface in layers — fix the first layer, re-run, iterate.
Completion Criteria
- Four current documents per source module share baselines, contract, and Rust SHA; no duplicate exists.
- The roadmap records justified source-module-to-crate boundaries and a project-driven topology; actual manifests and member paths match it.
- Every object has a deterministic final-two-segments path;
MISPLACED remains incomplete until physically aligned.
- Every Java object, method, overload, and parameter has a disposition.
- Every source test/case has a lossless Rust implementation and every source asset has a byte-identical checked copy.
<project>-test is a workspace member at the selected path with publish = false and owns the full source-suite/differential command and artifact.
- Complete Java/Rust suites pass and full per-case differential is 100%
MATCH, with no harness failure or not-run case.
- Every dependency reuse, platform exclusion, blocker, exception, and Rust extension has precise evidence and honest denominator treatment.
- Every authored
.rs file is at most 800 physical lines; files above 500 and functions above the Clippy 100-line signal have recorded cohesion reviews, and any split preserves Java object boundaries.
- Unit tests are colocated only when they exercise focused module behavior; integration, differential, host, load, and whole-project suites live under
tests/ or the non-published test package.
- Production Rust files satisfy layout, documentation, import, and no-stub rules.
- Every source-documented object, member, parameter, return, exception, metadata tag, and semantic inline comment has a traceable Rust counterpart.
- The complete declared batch was implemented before any acceptance gate ran.
- One consolidated post-implementation parity audit covers the full frozen denominator; no object-by-object verification loop was used.
- High-value call chains have source-linked semantic mappings.
- Applicable differential, replay, concurrency, load, fuzz, host, and rollback gates have evidence or explicit open gaps.
- Final reporting separates structural, implementation, behavioral, integration, and production-readiness claims.
1---2name: rust-java-migration3description: Plan, execute, audit, and verify behavior-preserving migrations from Java Maven or Gradle projects to project-shaped Rust Cargo workspaces, including derived crate boundaries, scale-appropriate topology, 100% lossless source-test/case migration, byte-identical test assets, and complete per-case differential parity. Use when comparing repositories at module, package, object, file, method, parameter, documentation, example, test, fixture/data, dependency-reuse, JavaBean/script-property, concurrency, runtime-behavior, oversized Rust-file, or test-organization level; producing migration documents; continuing an incomplete port; or repairing workspace drift. Enforces source-authoritative inventories, Rust-native APIs, a 500-line cohesion-review threshold and 800-line authored-file blocker, idiomatic unit/integration test placement, strict non-completion states, frozen baselines, and unified verification.4---56# Java to Rust Migration78Migrate contracts and observable behavior, not Java syntax. Preserve the Java project's public concepts and source traceability while selecting Rust-native ownership, error, concurrency, async, serialization, and framework mechanisms.910## Mandatory migration layout1112- Derive the Rust directory from the Java package after the declared package root; preserve meaningful nested packages and never flatten, cross-place, or double-nest them.13- Convert the Java object name to acronym-aware `snake_case.rs`; keep the Rust type in `PascalCase` and do not add suffixes such as `_trait`.14- Keep one Java object as one Rust object boundary. Rust defines no universal file-length limit: treat up to 500 physical lines as normal, review 501–800 lines for cohesion, and block authored `.rs` files above 800 lines.15- Split only when a file mixes responsibilities. Retain one primary object file and use subordinate files for coherent implementation families without introducing a second migrated object; record every split or reviewed exception.16- Keep `lib.rs` and `mod.rs` to declarations and re-exports. Update parent modules after moves and qualify ambiguous external re-exports with `::`.17- Keep focused private-behavior unit tests in `#[cfg(test)]` modules when useful. Put public-boundary, cross-module, differential, host, and whole-project tests under `tests/` or a non-published `<project>-test` package; keep source fixtures under `<project>-test/tests/fixtures/`.1819Read [Directory path alignment](references/directory-path-alignment.md) and [Layout and governance](references/layout-and-governance.md), then run the layout audit after moves.2021## Scope and Routing2223Use this skill for full-project migrations, one Maven/Gradle module, parity audits, migration planning, or continuation of an existing Rust port.2425This is the Rust adapter of the [cross-language migration profile](references/cross-language-migration-profile.md). Route crate/layout/API, dependency, macro, and domain mechanics to the corresponding Rust skills. Route verification to `rust-java-migration-testing` plus relevant test skills.2627Do not modify migration code when the user requested only an audit, plan, or documentation. A plan-only or read-only request does not authorize running a write-producing document scaffolder: return the proposed four-document content in the response, use `--dry-run`, or write only to a user-approved destination. Do not broaden a module migration into a repository rewrite without authorization.2829## Required Inputs3031Resolve or explicitly mark unknown:3233- Java repository path, baseline commit/tag, build tool, JDK, and module scope.34- Exact Java module package root used for path mapping; do not pass only a repository or `src/main/java` root and guess which segments to strip.35- Rust repository path, baseline commit, toolchain/MSRV, workspace, and target platforms.36- Target-product topology inputs: independently published Rust units, dependency/feature/target/proc-macro/FFI boundaries, expected crate count, package families, root noise, other languages, and established paths.37- Compatibility goal: source-shape parity, public API parity, behavior parity, or production replacement.38- Dependency policy: license, MSRV, supported targets, unsafe policy, advisory policy, maintenance horizon, and acceptable transitive cost.39- Component-candidate sources and their observation date; distinguish team policy, researched candidates, declared dependencies, and verified adoption.40- Explicit exceptions, blocked external projects, unsupported JVM-only features, and completion deadline.41- Required host applications, real scripts, test data, concurrency model, load profile, and rollback mechanism.42- Existing migration documents and their authority; identify the single current four-document set before merging historical material.43- Complete source test roots/runner configuration, including every concrete test case, disabled test, fixture, script, corpus, golden file, resource, and data file. The source repository defines the denominator; do not narrow it to fit Rust.4445Never silently infer that the newest branch, a generated manifest, or an API registration list is the behavioral baseline.4647## Workflow4849Treat one declared Java source module and its Rust target crate/module as the default migration batch. A user-authorized multi-module scope may be one batch, but freeze its boundary before implementation. Apply: freeze scope/contracts → implement the batch → freeze → audit → unified verification.5051Dependency-ordered editing inside the implementation batch is allowed. Per-object completion loops are not.5253### 1. Freeze baselines and inspect repository state5455Record both repository SHAs, dirty worktrees, Java/Rust toolchains, module manifests, enabled features, and generated-code boundaries. Preserve existing Rust work and unrelated changes.5657Verify the Rust toolchain satisfies the workspace MSRV: an older default rustc fails with `rustc X is not supported by the following packages` — run gates via `rustup run <ver> cargo ...`, never silently lower `rust-version`.5859If a repository contains `.codegraph/`, use CodeGraph before text search or file-by-file reading:60611. Survey module/package/crate architecture.622. Query representative public types and overloaded methods.633. Trace high-value call chains across factories, registries, interceptors, serializers, persistence, networking, and concurrency.644. Query the Rust counterparts and their callers/tests.655. Refresh or re-query the module inventory before implementation if the index reports staleness.6667If no index exists, do not initialize one without authorization. Use language-aware tooling or targeted source inspection and disclose the weaker evidence.6869Read [CodeGraph parity audit](references/codegraph-parity-audit.md) for query patterns and inventory rules.70Read [Case-study lessons](references/case-study-lessons.md) when designing a large utility-library migration or an annotation/macro split.7172### 1.5. Derive Rust crate boundaries and workspace topology7374Do not map Maven/Gradle modules one-to-one to Cargo packages. Derive Rust packages from independent publishing/reuse, dependency/feature/target isolation, proc-macro or FFI constraints, and distinct lifecycles; source modules remain traceability scopes.7576Select placement with `rust-workspace`: small cohesive results are normally root-flat; real adapter/binding/example/test families support a hybrid; large, root-heavy, or multi-language repositories may use `crates/`. Counts are review triggers, not laws. Record the source-module-to-crate mapping, chosen topology, rejected alternatives, and compatibility plan in the roadmap. See [Layout and governance](references/layout-and-governance.md).7778### 2. Build inventories before implementation7980Create separate machine-readable or tabular inventories for:8182- Java Maven/Gradle modules and Rust crates.83- The source-module-to-crate mapping and why root-flat, hybrid, or contained/grouped paths fit this project.84- Java packages and Rust module directories.85- Classes, interfaces, enums, records, annotations, exceptions, and relevant inner types.86- For every object, the deterministic Rust path after removing the organization/module package root and retaining the final two remaining segments (or one/zero when fewer remain).87- Public/protected constructors and methods, including every overload.88- Parameter names, order, generic bounds, nullability, defaults, varargs, checked exceptions, and return contracts.89- Existing object, constructor, method, generic/value parameter, return, exception, metadata-tag, and semantic inline comments, with source anchors.90- Examples, tests, fixtures, scripts, configuration, resources, service descriptors, and docs.91- A source-test case manifest and asset manifest; record every concrete case and asset path/hash before copying resources byte-for-byte into Rust.92- A non-published `<project>-test` package owning project-level source replay, cross-component paths, and differential acceptance.93- Call paths and externally observable side effects.9495Exclude `package-info`, generated sources, BOMs, aggregators, test support, facades, and Rust-only infrastructure only through explicit categories. Do not hide them by changing the denominator.9697Freeze the inventory as the batch manifest before production edits. Cover the complete denominator, dependency order, shared mechanisms, component decisions, test disposition, and approved exceptions; do not discover scope object-by-object.9899Resolve `SKILL_DIR` from this `SKILL.md`; never assume a fixed install path. Run commands from the Rust migration root and prefer repository-relative inputs/artifacts.100101Run the static Rust layout audit as an early signal:102103```bash104python3 "$SKILL_DIR/scripts/audit_migration_layout.py" \105 --java-package-root ../java-project/source-module/src/main/java/org/example/module \106 --rust-root . \107 --retain-segments 2 \108 --require-source-comments \109 --fail-on-warning110```111112The script calculates expected paths and distinguishes missing from misplaced113objects. It also detects non-snake-case paths, multi-object files, facade114definitions, wildcard imports, stub macros/panics, empty function bodies, and115missing Chinese source comments. Record an approved 501–800-line cohesion review116with repeated `--reviewed-large-file path/to/file.rs`; this never exempts a file117above 800 lines. Any strict blocker keeps migration completion blocked; a clean118scan still does not prove Java/Rust semantic parity.119120### 3. Create four documents for every source module121122When documentation writes are authorized, generate a documentation directory for each Java module before implementation:123124```bash125python3 "$SKILL_DIR/scripts/scaffold_migration_docs.py" \126 --module source-module \127 --java-root ../java-project/source-module \128 --java-package-root ../java-project/source-module/src/main/java/org/example/module \129 --rust-root <selected-target-crate-or-workspace> \130 --output-dir docs/source-module \131 --java-baseline <sha-or-tag> \132 --rust-baseline <sha> \133 --retain-segments 2134```135136The command creates:1371381. `迁移路线图.md` — scope, baselines, phases, dependencies, risks, and evidence gates.1392. `对象级对照表.md` — every Java object and its Rust file/type/status.1403. `语义迁移对照表.md` — every behavior family and its Rust-native implementation.1414. `对象名称一致性检查.md` — counts, missing/extra/merged objects, names, methods, parameters, and logic gaps.142143Populate every placeholder from source evidence. A generated template is144`DRAFT`, not evidence and never completion. Keep documents synchronized with145code in the same change. Templates:146147- [Migration roadmap](assets/templates/迁移路线图.md)148- [Object mapping](assets/templates/对象级对照表.md)149- [Semantic mapping](assets/templates/语义迁移对照表.md)150- [Name consistency audit](assets/templates/对象名称一致性检查.md)151152Every one of the four documents must be independently detailed and must contain153the module's current migration contract: source/Rust SHAs, exact object154denominator, target root, `retain_segments = 2`, status snapshot, strict155completion rules, and that document's responsibility. Reject a title-only,156count-only, or placeholder-only document. As an anti-summary floor, require at157least three substantive level-2 sections plus an evidence table or task matrix;158use a repository-configured size floor (45 nonblank lines by default) while159allowing a proportionally smaller generated object table for a genuinely tiny160module.161162Every document must show separate Java and Rust baselines, its last-audited date,163and a document status. Every migrated/verified row needs an evidence anchor:164source file or symbol, target file or symbol, test/oracle, exact command, and165artifact where applicable. During implementation, do not upgrade rows one at a166time. After the batch freeze, cross-check all four documents against the current167Rust SHA and update statuses in one consolidated pass. A later count table must168not silently contradict a technical-requirements document or an earlier semantic169gap.170171Keep exactly one current four-document set at the module root. Do not leave172`*-历史详细版.md` or a second `history/**/<current-name>.md` beside it. Merge173useful old package grouping, design context, and decision history into a clearly174delimited “历史设计附录” in the corresponding current document. The generated175current-fact region must remain first and regeneration must preserve the176appendix. Old counts, paths, statuses, tests, and completion marks never override177current facts.178179Treat scaffold `--force` as destructive and use it only for a disposable,180untouched `DRAFT`; never use it to merge or refresh a populated current181document. Merge historical details into the current document in place and182preserve both its generated fact region and existing appendix.183184### 4. Classify every object honestly185186Use these object states consistently. Keep verification levels (`V0`–`V7`)187separate; do not invent a friendlier state or translate a test result directly188into an object state.189190| State | Meaning |191|---|---|192| `MISSING` | Expected Rust object file does not exist |193| `MISPLACED` | Same-name file/type exists but not at the deterministic expected path |194| `STUB` | Shape or placeholder exists but real behavior is absent |195| `PARTIAL` | Real behavior exists but methods, callbacks, errors, ordering, lifecycle, or integration semantics are incomplete |196| `UNVERIFIED` | File/logic exists but source comments, object boundary, or semantic test evidence is insufficient |197| `IMPLEMENTED` | Expected path, one-object boundary, real complete logic, Chinese source semantics, and current semantic tests all exist |198| `DEPENDENCY_REUSED` | A pinned dependency provides the exact capability; crate/version or commit, upstream symbol, adapter, and local integration test are recorded |199| `PLATFORM_NA` | The capability is genuinely JVM/bytecode/class-loader/platform-only and explicit evidence records why no Rust object applies |200| `RUST_EXTENSION` | Intentional Rust-only capability, excluded from Java parity numerator |201202Only `IMPLEMENTED`, `DEPENDENCY_REUSED`, and `PLATFORM_NA` count as handled203source objects. `MISSING`, `MISPLACED`, `STUB`, `PARTIAL`, and `UNVERIFIED` are204incomplete. `RUST_EXTENSION` never enters the Java denominator.205206Allow a planned placeholder only when the user explicitly approves it. Record207the blocker in the roadmap, but keep each affected object in its factual208`MISSING` or `STUB` state. A blocker is metadata, not a completion-like object209state.210211Never upgrade from `MISSING` merely because an object name appears in a manifest,212facade, `lib.rs`, `mod.rs`, re-export, generated registry, or compatibility213module. Never upgrade from `UNVERIFIED` merely because `cargo test` is green.214215### 5. Decide component replacements from contracts216217Do not map framework names directly. For every external Java component or framework subsystem:218219The Java source module remains authoritative for object names, package220structure, and public contracts. A Rust dependency is only an implementation221reuse boundary. Do not restructure the migration around the dependency's file222tree and do not copy dependency-owned implementations into local files merely223to improve parity counts. For AOP-like work, for example, Spring defines the224Advice/Interceptor/Advisor object inventory while an aspect crate may satisfy225specific runtime symbols through `DEPENDENCY_REUSED`.2262271. Extract the behavior contract: API shape, wire/storage format, ordering, failure taxonomy, lifecycle, transactions, concurrency, cancellation, backpressure, security, observability, and deployment assumptions.2282. Choose a replacement shape: standard library, direct crate, wrapped crate, trait plus adapters, explicit registry/SPI, compile-time macro/code generation, application-host responsibility, or proven `PLATFORM_NA`.2293. Check the common mapping table and candidate catalog as discovery starting points, never as automatic approval.2304. When no verified mapping fits, generate several English capability/protocol/constraint queries, search crates.io and companion primary sources, and shortlist five to ten candidates across std, direct crate, wrapper, trait/adapters, code generation, host responsibility, and exclusion shapes.2315. Route crates.io metadata collection and ecosystem-health comparison to `rust-crate-discovery` when available. Apply migration-specific contract and compatibility gates here; its numeric health score does not select the replacement.2326. Reject candidates that fail a required contract, license, MSRV/target, runtime/blocking, protocol, security, maintenance/ownership, or dependency-graph constraint before scoring.2337. Compare viable candidates using semantic fit, maintenance, adoption, docs/tests, project compatibility, security/supply chain, maturity, cost, and exit strategy. Interpret downloads, reverse dependencies, stars, release recency, and commits as contextual signals, not proof.2348. Spike the highest-risk semantic path for the top candidates before committing the architecture.2359. Record search queries and date, ownership, version/features, per-dimension evidence/confidence, rejected alternatives, escape hatch, and rollback plan.23610. Promote an object to `DEPENDENCY_REUSED` only when the exact upstream symbol,237 pinned dependency evidence, adapter boundary, and local integration test are238 all recorded. “The ecosystem has it” or “semantically similar” remains239 `UNVERIFIED`.240241For multiple target frameworks, define a framework-neutral contract and thin adapters, then run one shared conformance suite against every adapter. Keep runtime traits/types separate from thin procedural macros and generated code.242243Read [Component replacement decision SOP](references/component-replacement-sop.md), [crate replacement discovery and evaluation](references/crate-replacement-discovery.md), and [Component candidate catalog](references/component-candidate-catalog.md) before choosing or approving a third-party replacement. The catalog is discovery input, never an approval list; re-verify release, maintenance, license, MSRV, targets, advisories, unsafe/build-script surface, and required contracts at decision time.244245### 6. Complete the declared batch in one semantic implementation pass246247Read [Layout and migration rules](references/layout-and-governance.md),248[Directory path alignment patterns and error catalog](references/directory-path-alignment.md),249and [Semantic mappings](references/semantic-mappings.md) before changing code. Then250execute the entire frozen batch without object-level acceptance pauses:2512521. Establish the target module tree, shared errors, traits, registries, adapters,253 serialization rules, concurrency model, and dependency boundaries once.2542. Implement every mapped Java object and operation in dependency order. Keep255 exactly one primary `.rs` file per Java object and real logic in the256 corresponding object or explicit collaborator files.2573. Copy and translate JavaDoc semantics into Chinese Rust doc comments across258 the batch. Migrate every existing object comment, constructor/method comment,259 generic and value `@param`, `@return`, `@throws`, `@since`, `@deprecated`,260 relevant `@see`, and semantic inline comment without omission. Preserve the261 parameter-specific contracts. Keep Java-to-Rust name, signature, and exception262 mappings in the four migration documents; keep generated Rust documentation263 Rust-native.2644. Implement all mapped overload variants, examples, fixtures, source-test265 counterparts, Rust-specific obligations, and risk-driven tests as batch266 artifacts, but do not execute validation yet. Preserve 100% of source test267 inputs, assertions, error expectations, state, side effects, and cleanup.268 Copy source test files/data/resources without editing them; put any269 Rust-specific derivatives in separate files.2705. Maintain one deferred-issues ledger. Continue through local uncertainties;271 pause only for a blocker that changes the frozen public contract,272 architecture, dependency policy, or authorized scope.2736. When every non-exempt manifest row has real implementation, freeze the Rust274 batch. Only then update the four documents in bulk and enter audit.275276During this pass, do **not** run `cargo check`, tests, Clippy, coverage,277differential comparison, per-object CodeGraph re-queries, or per-object278completion reviews. Do not report an object as accepted merely because its file279was edited. Recovery commits are allowed, but they are not verification gates.280281Read [Comment migration contract and example](references/comment-migration.md)282before migrating documentation. Treat missing source comments as migration gaps,283not optional cleanup.284285### 7. Preserve naming and overload intent286287- Use `snake_case` for Rust directories, files, methods, and parameters.288- Use `PascalCase` for Rust types.289- Map `loadOrCreateAgentState(slotKey)` to `load_or_create_agent_state(slot_key)`.290- Remove the organization and declared source-module package root, then retain291 exactly the final two remaining package segments. Retain one when only one292 remains and place root-package objects at the crate root. Example:293 `factory/xml/support/Foo.java` → `xml/support/foo.rs`;294 `propertyeditors/PatternEditor.java` → `propertyeditors/pattern_editor.rs`.295- Keep `lib.rs` and `mod.rs` as declarations and re-exports only.296- Keep one Java class/interface/enum/record per Rust file; an inner builder tightly owned by the primary type may remain with it.297- Treat 500 physical lines as a cohesion-review threshold and 800 as the authored-file blocker. Split by responsibility rather than line ranges; no subordinate file may introduce another migrated object.298- Enable `clippy::too_many_lines` as a function/method review signal at its 100-line default; refactor long routines when they combine distinct responsibilities.299- Use Rust's idiomatic test organization: colocate focused unit tests in `#[cfg(test)]` modules, and place public-boundary, cross-module, differential, host, and whole-project tests in `tests/` or a test/testkit package.300- Record every intentional rename in both object and name-consistency documents.301302Rust has no method overloading. Keep one canonical snake_case name only when the signatures have one semantic operation. Give additional variants stable semantic suffixes such as `_with_charset`, `_into`, or `_from_reader`; record the exact Java signature mapped to each Rust function. Never collapse overloads that differ in defaults, validation, side effects, or error behavior.303304Apply the local `rust-api-design` conventions to every migrated public Rust305surface. Do not mechanically translate JavaBean accessors: prefer `name()` over306`get_name()` (except genuine lookup operations), `set_name(value)` for controlled307mutation, `name_mut()` only when it cannot bypass invariants,308`into_name()`/`into_inner()` for ownership transfer, semantic boolean predicates,309and chainable builders. Use `as_`/`to_`/`into_`, `From`/`TryFrom`/`AsRef` and310`IntoIterator` by their Rust meanings; do not use `Deref` to emulate Java311inheritance. Expose fields directly only when invariants and API evolution permit312it. Preserve validation, visibility, side effects, exceptions, synchronization,313and lazy-computation behavior.314315When a script, expression engine, serializer, reflection facade, or other316compatibility surface exposes Java property semantics, keep the Rust API317idiomatic and implement the old field/getter/setter behavior in an explicit318registry or member resolver. Record this relationship as mapping form319`ADAPTED`; this is orthogonal to completion status and still requires320`IMPLEMENTED`, `UNVERIFIED`, or another factual state.321322Read [Rust API and JavaBean property adaptation](references/rust-api-adaptation.md)323before migrating getters, setters, builders, or script-visible properties.324325### 8. Translate mechanisms, not frameworks literally326327Use this table as a common starting point, then verify the exact contract and328current crate evidence:329330| Java responsibility | Rust starting point |331|---|---|332| Jackson JSON annotations/modules | `serde`, `serde_json`, project-owned custom serializers |333| Jackson XML / JAXB-style XML | `quick-xml` plus explicit namespace, attribute, mixed-content, and ordering logic |334| `null`, checked exceptions | `Option<T>`; typed `thiserror` enums and `Result` |335| SLF4J/Logback/MDC | `tracing`, `tracing-subscriber`, explicit field/context propagation and redaction |336| `synchronized` / `ConcurrentHashMap` | ownership first; then std `Mutex`/`RwLock` or `DashMap` when the access pattern warrants it |337| `CompletableFuture`, scheduled executors | async futures, supervised Tokio tasks, cancellation tokens, timers/intervals; select a scheduler crate only for richer contracts |338| Reactor `Mono<T>` / `Flux<T>` | `async fn -> Result<T, E>`; bounded `Stream<Item = Result<T, E>>` |339| OkHttp / Apache HttpClient | `reqwest` for high-level clients; Hyper for protocol-level control; verify TLS, proxy, pool, redirect, retry, and streaming semantics |340| Spring MVC/WebFlux / JAX-RS | framework-neutral core plus approved Axum, Actix Web, Poem, or other thin host adapters |341| JDBC/JPA/MyBatis | SQLx, Diesel, SeaORM, RBatis, or another verified data layer selected by query, mapping, transaction, migration, and runtime contracts |342| Caffeine/Guava cache | Moka or a project-owned cache; verify eviction, TTL/TTI, loading, invalidation, and concurrency |343| Jedis/Lettuce | `redis`; verify cluster/sentinel, reconnect, pipeline/transaction, TLS, and async behavior |344| Kafka/RabbitMQ/Pulsar/NATS/MQTT | protocol-specific client such as `rdkafka`, Lapin, `pulsar`, `async-nats`, or `rumqttc`; require real-broker semantics and recovery tests |345| Protobuf / gRPC | Prost; Tonic plus Prost for gRPC |346| Bean Validation | `validator` or project-owned validation, kept separate from framework extractors |347| `java.time`, UUID/ULID, `BigDecimal`, regex | `time`/`chrono`, `uuid`/`ulid`, `rust_decimal`/`bigdecimal`, `regex`; choose representations and compatibility before crate preference |348| `.properties`, YAML, TOML, configuration binding | `java-properties`, `serde_yaml_ng`, `toml`, or a verified configuration crate plus project-owned precedence/profile rules |349| Apache Commons/Hutool general utilities | std first, then focused crates such as `url`, `bytes`, `regex`, `base64`, or `hex`; do not seek one umbrella crate by name |350| Micrometer/OpenTelemetry/Prometheus | `metrics`, OpenTelemetry ecosystem, Prometheus exporters, and `tracing` integration; preserve names, labels, cardinality, context, and shutdown |351| JavaMail | `lettre`; verify MIME, attachment, TLS/authentication, retry, and delivery reporting |352| JWT/passwords/general crypto | `jsonwebtoken`, `argon2`, and focused RustCrypto crates; select algorithms/formats from the security contract, never from convenience alone |353| Groovy/Nashorn/embedded scripts | `rhai`, `boa_engine`, `mlua`, PyO3, or Wasmtime according to language, sandbox, resource-limit, threading, and packaging requirements |354| Apache POI/document formats | format-specific crates such as `rust_xlsxwriter`, `calamine`, `docx-rs`, `printpdf`, or `lopdf`; validate actual Office/PDF fixtures and unsupported features |355| ServiceLoader/SPI | explicit registry first; `inventory` only when link-time registration is required |356| Spring IoC/AOP/runtime annotations | constructors/builders, traits, middleware, registries, wrappers; use macros only for compile-time behavior |357| FreeMarker / Velocity / compile-time views | Tera / Handlebars; Askama for compile-time templates; maud for Rust-native markup |358| Lombok data boilerplate | standard derives plus invariant-preserving APIs/builders; evaluate `lombok-macros` only against the generated API contract |359| JUnit/Testcontainers | Rust unit/integration tests; `testcontainers` for disposable real dependencies |360| JNI/manual Swift/Kotlin/Python bindings | UniFFI when its supported type/error/async model fits; shipping and packaging remain separate work |361362Prefer composition of mature Rust crates over recreating a Java all-in-one implementation, but retain the source project's observable facade when compatibility requires it.363364### 9. Extract annotation behavior behind a stable macro boundary365366Do not place procedural macro entry points in a normal runtime crate. Use:367368```text369project-core # runtime traits, types, errors, and generated-code contract370project-macros # thin proc-macro entry points and syntax parsing371project-web-* # framework adapters that may re-export approved macros372```373374Use `-derive` only for a derive-only public surface; use `-macros` for attribute/function-like or mixed macros, unless the existing crate family has a deliberate established spelling. Keep generated code dependent on public runtime APIs, not proc-macro internals. Test expansion success, compile failures, generics, visibility, renamed dependencies, and each framework re-export.375376Java runtime annotations do not automatically become Rust macros. Use middleware, traits, registries, or explicit builders when runtime state and dynamic dispatch own the behavior.377378### 10. Audit once, then verify the complete batch379380After the implementation freeze, execute the applicable ladder for the whole381declared batch:3823831. Run one consolidated CodeGraph/static parity audit over all objects, files,384 exact signatures, parameters, overloads, call paths, dynamic boundaries,385 examples, tests, docs, and placeholders. Compare the complete Java comment386 inventory with Rust object, method, parameter, return, error, metadata, and387 inline comments. Reconcile all four documents in one pass.3882. Run Rust formatting, check, unit, doc, integration, Clippy, feature, target,389 and platform gates as one unified engineering suite.3903. Run every ported/mirrored Java contract test, clearly labeled as391 non-differential evidence.3924. Run the complete pinned Java suite and the complete Rust lossless-port suite,393 then run the complete Java golden exporter or live Java/Rust differential394 suite over every concrete source case. Require both suites to pass and every395 case to report `MATCH`; zero mismatches, harness failures, and not-run cases.396 Execute this from the dedicated `<project>-test` package; local397 production-crate tests remain subsystem evidence only.3985. Replay the complete set of real user scripts and examples against both399 implementations.4006. Run concurrency acceptance for ordering, cancellation, backpressure, races,401 shutdown, and Loom/model properties where useful.4027. Run load/stability tests for throughput, latency percentiles, memory,403 handles/tasks, reconnects, and soak.4048. Run security property tests, malformed-input suites, `cargo-fuzz`, unsafe405 review, dependency advisories, and secret-redaction checks.4069. Run real business-host integration with databases, networks, files,407 frameworks, and deployment topology.40810. Run the gray rollout and rollback drill with recorded recovery time and409 state compatibility.410411When a gate fails, group failures by shared subsystem or root cause, repair the412batch, and rerun the affected consolidated gate plus downstream invalidated413gates. Never fall back to migrate-compare-test one object at a time.414415Read [Verification and acceptance](references/verification-and-acceptance.md) for evidence design and use `rust-java-migration-testing` for the three-ledger testing SOP. Before repairing a non-compiling or warning-heavy workspace, read [Compile drift and migration cleanup](references/compile-drift-and-cleanup.md): dependency/version drift, MSRV, crate-root re-export chain breaks, duplicate cross-crate types, Java-mirror naming/scaffolding norms, and the zero-warning check workflow (default + `--all-features`, `--keep-going` layered errors, per-crate attribution, tests after cleanup).416417### 11. Report completion without inflating coverage418419Report structural, implementation, behavioral, test, integration, and production420readiness separately. For behavior, distinguish mirrored contracts, golden421differential, live differential, and approved equivalent oracles; for tests,422separate losslessly migrated source tests from Rust-native additions.423424Include exact commands, SHAs, test counts, failures, exceptions, and unverified boundaries. Never call a migration complete because code compiles or a parity manifest reaches 100%.425426## Red Lines427428- Do not define many migrated objects in `lib.rs`, `mod.rs`, or `compat.rs`.429- Do not delegate every object to one `compat.rs` implementation.430- Do not use empty bodies, `todo!()`, or `unimplemented!()` as completed migration.431- Do not delete or simplify working migrated behavior to make counts align.432- Do not use wildcard imports in production migration code.433- Do not silently merge several Java objects into one Rust file.434- Do not keep an authored `.rs` file above 800 physical lines; review every file above 500 and split it when cohesion is weak.435- Do not mechanically compress code, remove useful comments, or split arbitrary line ranges merely to satisfy a size gate.436- Do not embed integration, differential, host, load, or whole-project acceptance suites in production modules; inline `#[cfg(test)]` unit tests remain valid for focused module-private behavior.437- Do not replace overloaded behavior with one lossy convenience function.438- Do not create `get_*` methods solely to mirror JavaBean spelling when an idiomatic Rust method plus an explicit compatibility adapter preserves the contract.439- Do not treat an idiomatic Rust getter/setter as sufficient when scripts or dynamic member access still require Java field/getter/setter resolution.440- Do not call a declared dependency, successful compile, or isolated POC a verified component replacement.441- Do not use a replacement dependency's package/file layout as the target object inventory; source Java objects and the deterministic path rule remain authoritative.442- Do not mark a semantically similar dependency as `DEPENDENCY_REUSED` without pinned crate/commit, exact source symbol, adapter evidence, and local integration tests.443- Do not use `PLATFORM_NA` for work that is merely difficult or missing; require JVM/bytecode/class-loader/platform-specific evidence.444- Do not promote a component copied from a research list or local convention document to “selected” without current hard-filter and contract evidence.445- Do not call a Rust test copied from a Java test a differential test unless both implementations or Java-produced golden artifacts participate.446- Do not declare source-test parity from dispositions alone. Every source case needs a lossless target and golden/live `MATCH`; `MISSING`, `BLOCKED`, and `NOT_APPLICABLE` block completion.447- Do not modify copied source fixtures, scripts, corpora, golden files, or test data in place. Verify source/target SHA-256 and keep generated derivatives separate.448- Do not treat independently green suites or equal test totals as parity; compare per-case outputs, errors, state, side effects, and cleanup.449- Do not substitute production/binding-crate local tests for the non-published `<project>-test` whole-project acceptance package.450- Do not copy Maven/Gradle modules one-to-one into Cargo packages without a Rust publishing, dependency, target, macro/FFI, or lifecycle reason.451- Do not force every workspace into `crates/` or root-flat; record topology from product scale, families, repository noise, and compatibility.452- Do not mark a row behavior-verified from file counts, parser acceptance, generic `is_ok()`/`is_err()`, or “at least one test per object”.453- Do not let the four migration documents carry different baselines or contradictory completion states.454- Do not keep a current document and a `-历史详细版`/nested duplicate; merge useful history after the generated fact region.455- Do not replace the generated current-fact region or let regeneration discard the merged appendix.456- Do not claim real testing when only mocks, compilation, or static inspection ran.457- Do not edit reference source repositories while extracting patterns.458- Do not alternate migration, comparison, and testing for each object, file, or method.459- Do not run object-scoped acceptance during implementation; finish the frozen batch before consolidated audit and unified verification.460- Do not convert recovery commits or local edit milestones into completion checkpoints.461- Do not omit an existing Java object, constructor, method, parameter, return, exception, lifecycle, thread-safety, deprecation, or semantic inline comment.462- Do not replace source documentation with generic prose or claim comment parity from `cargo doc` alone.463- Do not write `对应 Java` in parameter, return, error-variant, field, or inline comments. Limit optional anchors to Rust type and constructor/method docs; keep detailed correspondence in the four documents.464- Do not rename Java-mirror SCREAMING_SNAKE enum variants or delete Java-mirror scaffolding types to silence `non_camel_case_types`/`dead_code`; use `#[allow(...)]` + comment and keep the Java inventory intact.465- Do not declare a workspace clean from the default-features gate alone; `--all-features` must also reach zero warnings, and do not silently lower `rust-version` to match an old local rustc — run the pinned toolchain via `rustup run <ver> cargo ...`.466- Do not edit a path dependency while cleaning a dependent crate; attribute each warning to its owning crate's `-->` path first.467- Do not fix "all errors" from one `--keep-going` output; errors surface in layers — fix the first layer, re-run, iterate.468469## Completion Criteria470471- Four current documents per source module share baselines, contract, and Rust SHA; no duplicate exists.472- The roadmap records justified source-module-to-crate boundaries and a project-driven topology; actual manifests and member paths match it.473- Every object has a deterministic final-two-segments path; `MISPLACED` remains incomplete until physically aligned.474- Every Java object, method, overload, and parameter has a disposition.475- Every source test/case has a lossless Rust implementation and every source asset has a byte-identical checked copy.476- `<project>-test` is a workspace member at the selected path with `publish = false` and owns the full source-suite/differential command and artifact.477- Complete Java/Rust suites pass and full per-case differential is 100% `MATCH`, with no harness failure or not-run case.478- Every dependency reuse, platform exclusion, blocker, exception, and Rust extension has precise evidence and honest denominator treatment.479- Every authored `.rs` file is at most 800 physical lines; files above 500 and functions above the Clippy 100-line signal have recorded cohesion reviews, and any split preserves Java object boundaries.480- Unit tests are colocated only when they exercise focused module behavior; integration, differential, host, load, and whole-project suites live under `tests/` or the non-published test package.481- Production Rust files satisfy layout, documentation, import, and no-stub rules.482- Every source-documented object, member, parameter, return, exception, metadata tag, and semantic inline comment has a traceable Rust counterpart.483- The complete declared batch was implemented before any acceptance gate ran.484- One consolidated post-implementation parity audit covers the full frozen denominator; no object-by-object verification loop was used.485- High-value call chains have source-linked semantic mappings.486- Applicable differential, replay, concurrency, load, fuzz, host, and rollback gates have evidence or explicit open gaps.487- Final reporting separates structural, implementation, behavioral, integration, and production-readiness claims.