Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
169 commits
Select commit Hold shift + click to select a range
4dd8394
fix(cpp): freeze registries before root access
chaokunyang Aug 27, 2026
0efb355
fix(csharp): freeze registries and clear failed roots
chaokunyang Aug 27, 2026
cccebac
fix(go): freeze registries and restore root buffers
chaokunyang Aug 27, 2026
826868a
fix(java): freeze shared facades and clear root state
chaokunyang Aug 27, 2026
6a3546e
fix(javascript): freeze registries and clear root state
chaokunyang Aug 27, 2026
8e8ee73
fix(python): freeze registries and finalize configured types
chaokunyang Aug 27, 2026
ba3b5f7
fix(jvm): gate generated serializer registration
chaokunyang Aug 27, 2026
29c86a0
fix(swift): retain registry finalization failures
chaokunyang Aug 27, 2026
811cc40
docs: define root registry lifecycle ownership
chaokunyang Aug 27, 2026
37531ff
test(javascript): expect failed root write cleanup
chaokunyang Aug 27, 2026
8df5f66
fix(javascript): restore root state before reuse
chaokunyang Aug 27, 2026
41219c3
fix(jvm): recheck registry after serializer construction
chaokunyang Aug 27, 2026
6584bd7
fix(javascript): clear root metastring owners
chaokunyang Aug 27, 2026
1ab4a91
docs(python): fix circular reference example
chaokunyang Aug 27, 2026
77bb81f
test(swift): restore precise failure assertions
chaokunyang Aug 27, 2026
a0fd34b
docs(javascript): define metadata owner reset
chaokunyang Aug 27, 2026
a40934d
fix(javascript): reuse bounded metastring owners
chaokunyang Aug 27, 2026
5a53780
docs(javascript): define bounded owner reset
chaokunyang Aug 27, 2026
178aa89
fix(csharp): recheck lifecycle after registration callbacks
chaokunyang Aug 27, 2026
1cb3d4b
fix(python): recheck registry after serializer construction
chaokunyang Aug 27, 2026
a44aeeb
docs: define callback-safe registry publication
chaokunyang Aug 27, 2026
b8fb74f
fix(csharp): keep one failed-root reset owner
chaokunyang Aug 27, 2026
30500d7
fix(go): validate factories before registry publish
chaokunyang Aug 27, 2026
257f24f
refactor(go): remove duplicate root cleanup
chaokunyang Aug 27, 2026
7b391d3
test(csharp): avoid pinning root error type
chaokunyang Aug 27, 2026
30e3e0c
refactor(cpp): keep registration checks in one owner
chaokunyang Aug 27, 2026
c2fd1a0
refactor(python): preserve carrier invariants
chaokunyang Aug 27, 2026
3340108
fix(java): close facade registration callbacks
chaokunyang Aug 27, 2026
4d8d28d
refactor(jvm): reuse registration owners
chaokunyang Aug 27, 2026
958c971
fix(python): publish registrations after callbacks
chaokunyang Aug 27, 2026
5c9ea48
docs: clarify registration lifecycle
chaokunyang Aug 27, 2026
6ece493
fix(javascript): publish generated registries atomically
chaokunyang Aug 27, 2026
b680222
docs: define registry publication owners
chaokunyang Aug 27, 2026
8fb91e3
fix(go): keep registry diagnostics callback-free
chaokunyang Aug 27, 2026
c2187cc
fix(swift): reject reentrant registry finalization
chaokunyang Aug 27, 2026
e428531
fix(python): revalidate nested registrations
chaokunyang Aug 27, 2026
9d7b8bb
fix(python): reject root reentry during pool builds
chaokunyang Aug 27, 2026
946f3ca
fix(javascript): freeze generated schema publication
chaokunyang Aug 27, 2026
1eb5fe6
fix(jvm): finalize registry publication atomically
chaokunyang Aug 27, 2026
980b640
docs: align lifecycle ownership guidance
chaokunyang Aug 27, 2026
1bec57b
docs(python): distinguish dynamic resolution from registration
chaokunyang Aug 27, 2026
50e7df0
fix(csharp): publish registrations atomically
chaokunyang Aug 27, 2026
d3e41eb
fix(python): keep pooled serializers instance-owned
chaokunyang Aug 27, 2026
20b66fe
fix(javascript): publish generated serializers once
chaokunyang Aug 27, 2026
3e1a729
fix(jvm): keep module lifecycle in Fory
chaokunyang Aug 27, 2026
35a0728
fix(java): publish serializer construction atomically
chaokunyang Aug 28, 2026
148bd13
fix(java): retain canonical serializer owners
chaokunyang Aug 28, 2026
b8855d2
perf(javascript): reuse metadata owner counters
chaokunyang Aug 28, 2026
565e0a8
perf(cpp): avoid repeated pool finalization
chaokunyang Aug 28, 2026
277cf64
refactor(csharp): remove stale registry state
chaokunyang Aug 28, 2026
1937739
refactor(python): restore read cleanup owner
chaokunyang Aug 28, 2026
a94052c
fix(java): publish late children atomically
chaokunyang Aug 28, 2026
ef2db12
refactor(java): keep lifecycle logic in owners
chaokunyang Aug 28, 2026
a6f1802
fix(jvm): keep generated serializers unpublished
chaokunyang Aug 28, 2026
8661b79
fix(python): replay semantic registrations
chaokunyang Aug 28, 2026
018f034
docs(jvm): define generated serializer ownership
chaokunyang Aug 28, 2026
de4fd8b
fix(javascript): enforce one schema owner
chaokunyang Aug 28, 2026
3d9ac1f
docs: define generated schema ownership
chaokunyang Aug 28, 2026
ac1826b
test(javascript): shorten lifecycle names
chaokunyang Aug 28, 2026
3ad1574
fix(python): preserve reduce iterator carriers
chaokunyang Aug 28, 2026
7802abb
refactor(javascript): remove legacy metadata adapter
chaokunyang Aug 28, 2026
eb8f1b5
fix(javascript): reject schema identity conflicts
chaokunyang Aug 28, 2026
f98e522
docs: align lifecycle ownership rules
chaokunyang Aug 28, 2026
ef71763
chore(scala): restore unchanged test spacing
chaokunyang Aug 28, 2026
d24d85f
fix(javascript): keep schema owners authoritative
chaokunyang Aug 28, 2026
7d9eba6
docs: align root lifecycle ownership
chaokunyang Aug 28, 2026
24f02c9
test(javascript): cover named schema conflicts
chaokunyang Aug 28, 2026
efaf931
fix(csharp): preserve registry identity owners
chaokunyang Aug 28, 2026
c46bb05
fix(go): preserve registry identity owners
chaokunyang Aug 28, 2026
96e25dd
docs(javascript): describe open union behavior
chaokunyang Aug 28, 2026
16572ab
fix(cpp): preserve registry identity owners
chaokunyang Aug 28, 2026
41690d4
refactor(cpp): match registry key storage
chaokunyang Aug 28, 2026
7a41bd3
perf(cpp): avoid repeated pool finalization
chaokunyang Aug 28, 2026
23c0cfc
perf(cpp): isolate registration-only synchronization
chaokunyang Aug 28, 2026
8e7daf6
test(kotlin): keep freeze probes owner-local
chaokunyang Aug 28, 2026
595531f
docs: clarify metadata logical reset
chaokunyang Aug 28, 2026
3f62b42
fix(scala): reject callbacks after failed freeze
chaokunyang Aug 28, 2026
be97f4a
fix(go): normalize registration type owners
chaokunyang Aug 28, 2026
60398e1
fix(java): gate resolver registration entries
chaokunyang Aug 29, 2026
328d55a
fix(javascript): reconcile generated serializer owners
chaokunyang Aug 29, 2026
cd156f0
fix(python): enforce registry finalization ownership
chaokunyang Aug 29, 2026
6316f6c
refactor(python): remove unused range index state
chaokunyang Aug 29, 2026
83e4893
docs(python): align callable and serializer setup
chaokunyang Aug 29, 2026
00b99ba
perf(cpp): preserve byte root call shape
chaokunyang Aug 29, 2026
59e300f
perf(go): make root freeze idempotent
chaokunyang Aug 29, 2026
8cdda40
docs: distinguish native resolution from registration
chaokunyang Aug 29, 2026
b73c783
Merge remote-tracking branch 'apache/main' into root-lifecycle-policy
chaokunyang Aug 29, 2026
956210e
refactor(csharp): simplify registry freeze lifecycle
chaokunyang Aug 29, 2026
b238162
refactor(cpp): keep registry freeze single-owned
chaokunyang Aug 29, 2026
285f608
refactor(javascript): remove registration transactions
chaokunyang Aug 29, 2026
efc24ea
docs(csharp): clarify thread-safe registry ownership
chaokunyang Aug 29, 2026
5ecc19c
refactor(cpp): derive context readiness from owners
chaokunyang Aug 29, 2026
9d46353
refactor(go): remove thread-safe registry replay
chaokunyang Aug 29, 2026
c5313b9
refactor(swift): freeze registry without finalization state
chaokunyang Aug 29, 2026
6465d70
refactor(python): remove registry finalization machinery
chaokunyang Aug 29, 2026
88adec8
refactor(cpp): clarify context resolver construction
chaokunyang Aug 29, 2026
8cc3296
refactor(csharp): name version hash cache precisely
chaokunyang Aug 29, 2026
7f1715a
test(go): remove stale facade setup split
chaokunyang Aug 29, 2026
e3cb41e
test(swift): keep registry lifecycle cases focused
chaokunyang Aug 29, 2026
6be170a
fix(python): recheck registry before explicit publication
chaokunyang Aug 29, 2026
d197185
refactor(javascript): remove stale metadata adapters
chaokunyang Aug 29, 2026
28b4b4f
fix(javascript): clear failed roots immediately
chaokunyang Aug 29, 2026
02a14de
fix(python): publish automatic type IDs on success
chaokunyang Aug 29, 2026
dde640c
test(swift): remove unrelated superclass restriction
chaokunyang Aug 29, 2026
fb9aed0
fix(csharp): preserve checked metadata across failed roots
chaokunyang Aug 29, 2026
63bf2a7
test(python): prove failed registration keeps type IDs
chaokunyang Aug 29, 2026
149d235
fix(python): keep pooled serializers child-owned
chaokunyang Aug 29, 2026
62089de
test(python): rely on native iterator discovery
chaokunyang Aug 29, 2026
afed479
refactor(csharp): keep read context unchanged
chaokunyang Aug 29, 2026
5cdb1e4
refactor(csharp): replay registrations only at child creation
chaokunyang Aug 29, 2026
4616639
refactor(jvm): simplify registry freeze ownership
chaokunyang Aug 29, 2026
7bce016
fix(python): keep explicit serializer ownership local
chaokunyang Aug 29, 2026
5ca463c
test(python): exercise the registered serializer owner
chaokunyang Aug 29, 2026
de197b3
refactor(cpp): complete type metadata in context owners
chaokunyang Aug 29, 2026
f1fdfb6
fix(csharp): restore failed root state immediately
chaokunyang Aug 29, 2026
3853d22
refactor(python): keep registry freeze to one flag
chaokunyang Aug 29, 2026
753092a
docs(go): keep registry freeze to existing owners
chaokunyang Aug 29, 2026
43873ae
refactor(swift): keep lazy metadata completion minimal
chaokunyang Aug 29, 2026
7d37c0c
fix(jvm): preserve facade serializer ownership
chaokunyang Aug 29, 2026
9f04029
refactor(javascript): remove registration transaction remnants
chaokunyang Aug 29, 2026
c300426
docs: define root lifecycle ownership
chaokunyang Aug 29, 2026
5eded1c
docs(javascript): retain metadata cache ownership note
chaokunyang Aug 29, 2026
2690eef
fix(python): preserve compatible enum placeholder
chaokunyang Aug 29, 2026
c9df37a
test(javascript): use generated registry handles
chaokunyang Aug 29, 2026
f0b88d2
test(javascript): resolve IDL roots from registrations
chaokunyang Aug 29, 2026
3643238
perf: keep lifecycle slow paths cold
chaokunyang Aug 29, 2026
9823baf
docs: clarify registry freeze ownership
chaokunyang Aug 29, 2026
92c56ad
perf: keep registry lifecycle checks on owner paths
chaokunyang Aug 29, 2026
3391917
perf: keep facade freeze checks direct
chaokunyang Aug 29, 2026
5e82d6e
perf(cpp): keep lazy metadata off hot paths
chaokunyang Aug 29, 2026
becd70a
perf(python): keep registry freeze on compiled owner
chaokunyang Aug 29, 2026
015a010
fix(java): freeze blocked reads before input access
chaokunyang Aug 29, 2026
584caf1
fix(javascript): clean failed serializer lookup state
chaokunyang Aug 29, 2026
cfe6bcd
fix(csharp): close failed root cleanup gaps
chaokunyang Aug 29, 2026
76eeb59
fix(java): close registry setup boundary
chaokunyang Aug 30, 2026
7284ab4
docs: align lifecycle guidance with registry owners
chaokunyang Aug 30, 2026
af3d999
refactor(cpp): remove resolver lifecycle tag
chaokunyang Aug 30, 2026
934ef17
refactor: remove redundant lifecycle drift
chaokunyang Aug 30, 2026
1358f4e
docs: remove stale lifecycle examples
chaokunyang Aug 30, 2026
9075e30
test: exercise failed lookup cleanup directly
chaokunyang Aug 30, 2026
f4314ca
docs: clarify dynamic type registration
chaokunyang Aug 30, 2026
4203ec7
fix(java): clean failed write roots
chaokunyang Aug 30, 2026
c3254bb
style(java): group serialize overloads
chaokunyang Aug 30, 2026
56dba80
test(java): keep registry tests on JDK 8
chaokunyang Aug 30, 2026
f61f31e
fix(java): simplify thread-safe registry freeze
chaokunyang Aug 30, 2026
3f2cc3a
fix(python): keep explicit registration atomic
chaokunyang Aug 30, 2026
29ae5ee
test(javascript): keep root cleanup coverage causal
chaokunyang Aug 30, 2026
1aa49bd
test(python): keep registry checks concise
chaokunyang Aug 30, 2026
2d8e856
fix(java): publish read context atomically
chaokunyang Aug 30, 2026
54d9af9
fix(python): preserve registry owners
chaokunyang Aug 30, 2026
64172a1
fix(java): keep registry freeze owner-local
chaokunyang Aug 30, 2026
37088f4
perf(java): isolate registry snapshot publication
chaokunyang Aug 30, 2026
62e98ce
fix(java): serialize facade setup before child freeze
chaokunyang Aug 30, 2026
2d50b90
test(java): keep facade freeze race focused
chaokunyang Aug 30, 2026
b2ab955
perf(python): freeze compiled roots without a branch
chaokunyang Aug 30, 2026
ef96201
fix(javascript): clean up failed input binding
chaokunyang Aug 30, 2026
3744b40
fix(java): keep builder module dedupe
chaokunyang Aug 30, 2026
b85458e
fix: remove noncausal registry policies
chaokunyang Aug 30, 2026
9372a95
test(python): retain stateful reproduction coverage
chaokunyang Aug 30, 2026
df45915
perf(swift): avoid repeated registry freeze stores
chaokunyang Aug 30, 2026
89c413e
fix(javascript): guard nested registration publication
chaokunyang Aug 30, 2026
67b819a
fix(csharp): publish custom serializers before root only
chaokunyang Aug 30, 2026
2a9818d
fix(swift): recheck registry before publication
chaokunyang Aug 30, 2026
54acd63
docs: define callback-safe registry publication
chaokunyang Aug 30, 2026
bbd9846
fix: guard reentrant registry publication
chaokunyang Aug 30, 2026
a62acd7
docs: preserve failed-root cleanup invariants
chaokunyang Aug 30, 2026
fe97d41
refactor: remove noncausal lifecycle drift
chaokunyang Aug 30, 2026
ca67563
docs: register thread-safe types before root use
chaokunyang Aug 30, 2026
c08c383
docs: keep registry snapshots separate from lifecycle
chaokunyang Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .agents/languages/cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ Load this file when changing `cpp/`, Cython build plumbing, or C++ xlang behavio
resource amplification, publish reference or cache state that survives root cleanup, or return
success past the required safepoint. Do not add per-field checks, cursor rollback, or tests that
pin the first detection point solely to make an error earlier or more precise.
- Every public `Fory` and `ThreadSafeFory` root serialization or deserialization overload freezes
explicit registration before codec work. Route facade and resolver registration through one
authoritative frozen flag for that registry. Do not add another lifecycle flag or a multi-state
machine around the existing read/write-context resolver construction.
- A root freezes explicit registration before the existing read/write-context construction clones
the registered resolver tables. Context construction must not eagerly complete every registered
`TypeInfo`; complete metadata only when a context first uses that type for metadata,
struct-version, or skip behavior. Keep ordinary type lookup free of completion work.
- Keep the registration check out of normal runtime lookup hot paths.
- Direct `Fory` and its resolver are creator-thread-owned. Configure `ThreadSafeFory` before
concurrent use and let that facade own first-root synchronization; do not add a resolver mutex to
support concurrent registration that neither facade permits.
- Put private methods last in class definitions, immediately before private fields.
- Do not redesign alias-based or low-level public type shapes to add convenience methods unless the user explicitly asks for that API change.
- For cross-language feature ports, match protocol behavior but use idiomatic C++ ownership and layering instead of mirroring Java structure literally.
Expand Down
9 changes: 9 additions & 0 deletions .agents/languages/csharp.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ Load this file when changing `csharp/` or C# xlang behavior.
- C# code must build without compiler or analyzer warnings. Treat warnings as blockers in project, test, and generated code.
- Fory C# requires .NET SDK `8.0+` and C# `12+`.
- Use `dotnet format` to keep C# code style consistent.
- A direct C# `Fory` registry and the `ThreadSafeFory` public registration boundary each own one
authoritative frozen flag. The first root sets the owning flag before codec work and leaves it
set after failure. Explicit registration checks that flag before mutation. `ThreadSafeFory` keeps
its existing registration callbacks only to configure newly created child runtimes; do not
turn that list into another registry lifecycle state.
- Generated or custom serializer construction and `TypeInfo` creation can execute application
code. Complete them before explicit ID or name publication, then recheck the same `Fory` flag
immediately before publishing that registration. Do not publish an intermediate unregistered
`TypeInfo` for a custom binding.
- Generated C# gRPC service companions are compiler-owned files that depend on application-provided gRPC packages, not `csharp/src/Fory`. Keep gRPC package references out of the Fory runtime package.
- C# generated schema modules are source-file owners. Service companions must use that module's `ThreadSafeFory` and must not introduce namespace-owned aliases or duplicate serializer registration paths.
- C# external-type serialization is target-keyed. A local
Expand Down
4 changes: 2 additions & 2 deletions .agents/languages/dart.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ Load this file when changing `dart/`.
- Do not add parallel header-low/header-high slot caches or multi-slot recent caches in TypeMeta hot paths to chase benchmark gaps. Header-cache hits must use the concrete checked cache owner directly; if a hit hint is needed, cache one TypeInfo/TypeMeta object and compare the protocol-defined top 52 header bits on that object, not separate low/high header fields or benchmark-pattern state.
- The top 52 TypeDef/TypeMeta header bits are the schema identity. The full low 12 bits belong only to the current frame and must not participate in hit selection. On a hit, decode the current body size from its low eight bits and any extended-size varuint, prove those bytes readable, and skip exactly that body. Do not validate reserved/compress flags, compare cached or local low bits, parse or rehash the body, repeat schema or policy validation, or grow low-bit sentinels, accepted-header fields, parallel header slots, or benchmark-pattern state. The cold miss path owns low-flag validation.
- Dart expected-type TypeDef reads should compare only the top 52 bits of the expected `TypeInfo` object's cached local TypeDef header before consulting the parsed-metadata map. A match is a direct local-schema hit: use the current frame's size encoding only for bounds and skip, add the expected type to the per-read shared type table, and do not validate its low flags, publish to `ParsedTypeMetaCache`, record a remote schema version, or parse/hash the body.
- Dart local TypeDef construction is registration-owned: record registrations
and finalize their dependent TypeDefs and struct serializers before the first
- Dart local TypeDef construction is registration-owned: each explicit registration constructs its
dependent TypeDefs and struct serializers before the first
root read or write. The first `serialize`, `serializeTo`, `serializeBuiltin`,
`serializeBuiltinTo`, `deserialize`, or `deserializeFrom` call permanently
freezes that `Fory` instance's resolver;
Expand Down
6 changes: 6 additions & 0 deletions .agents/languages/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Load this file when changing `go/fory/` or Go xlang behavior.
- Run Go commands from within `go/fory/`.
- Changes under `go/` must pass formatting and tests.
- The Go implementation focuses on fast serializers.
- A Go `Fory` instance has one authoritative registry-frozen flag. The first root serialization or
deserialization sets it before codec work and leaves it set after failure. Explicit registration
checks that flag before mutation. Do not add another registry lifecycle state or alter existing
registration semantics beyond that boundary check.
`threadsafe.Fory` has no registration API or facade registry: configure every pooled child in the
factory passed to `NewWithFactory` before returning it.
- Go `ReadContext` intentionally defers codec errors to existing `HasError` or `CheckError`
boundaries. After an error, work may continue only while it remains panic- and bounds-safe and
cannot cause disproportionate work or allocation, publish state that survives root cleanup, or
Expand Down
43 changes: 43 additions & 0 deletions .agents/languages/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ Load this file when changing anything under `java/` or when Java drives a cross-
values; use qualified names only when a real name conflict requires it.
- If you run temporary tests with `java -cp`, run `mvn -T16 install -DskipTests` first so local Fory jars are current.
- `WriteContext`, `ReadContext`, and `CopyContext` must stay explicit. Do not reintroduce `ThreadLocal` or ambient runtime-context patterns.
- Java scoped meta-share TypeInfo occurrences are root-local, and the current table size is their
protocol visibility boundary. Reset tables of at most 8192 entries by setting the size to zero;
do not null retained slots. Only when the size exceeds 8192 may cleanup replace the backing array,
and it must restore a small eight-slot array instead of retaining or allocating 8192 slots. Keep
the normal root-cleanup path allocation-free, and do not add count-shape specializations.
- Deserialization failures must not copy or retain the active reference table or materialized graph
in the exception. Root reset owns releasing operation-local graph state; keep failure reporting
bounded independently of graph size.
- Java root deserialization graph memory budgeting belongs to `ReadContext`
and is initialized by `Fory` root APIs. Public config is `maxGraphMemoryBytes`
with fixed `128 MiB` default. Positive explicit values override the default;
Expand Down Expand Up @@ -76,6 +84,41 @@ Load this file when changing anything under `java/` or when Java drives a cross-
work, dynamic stream bytes-read accounting, or stale narrower-scope formulas.
- Generated serializers must not retain runtime context fields. `Fory` should stay a root-operation facade rather than accumulating serializer or convenience state.
- When the serializer class and constructor shape are known at the call site, prefer direct constructor lambdas or direct instantiation over reflective `Serializers.newSerializer(...)`.
- Each natural Java registry or public facade boundary owns one authoritative lifecycle flag. A
concrete resolver owns its local frozen flag; a thread-safe facade uses the shared registry's
frozen flag for the facade-wide boundary. The first root serialization or deserialization sets the
owning fact before codec work and never clears it, including after failure. Every explicit type,
serializer, module, name, ID, or type-checker binding checks that fact before mutation.
Disallow-list changes use the bound checker's resolver listeners. Do not add another lifecycle
state or a parallel registration-commit path.
- Direct and thread-safe facades expose module registration before their first root. Kotlin and
Scala registration extensions target `BaseFory`; do not narrow them to concrete `Fory` or make
builder installation the only thread-safe path. A thread-safe facade's shared registry owns its
registration boundary so a root started by any child closes the facade before registration can
mutate another child. Non-root `execute` and copy operations remain concurrent and do not freeze
registration. Complete facade registration before concurrent serialization, deserialization,
copy, or `execute` calls begin; do not serialize those operations behind a registration lock.
- `ForyModule.install` is registration-only setup. It may install nested modules and construct
child-specific serializers, but must not start a root through the supplied child or a captured
direct or thread-safe facade. Do not propagate the facade lifecycle owner into raw child
registration to support this invalid reentrancy; frozen-facade replay needs the unexposed child
to remain governed by its local resolver until it adopts the shared snapshot.
- Live thread-safe facade registration carries the existing `SharedRegistry` check through
application-controlled serializer preparation and runs it immediately before child publication.
Replay into a new, unexposed thread-local child instead uses that child's local resolver check,
then freezes the child onto the shared snapshot before exposure. Do not make every child resolver
consult the shared frozen flag: that would reject the required frozen-facade setup replay.
- `ThreadSafeFory.execute` exposes one borrowed child only for the callback. Do not retain that
child or register through it; use the facade registration methods so every current and future
child receives the same setup.
- Serializer completion used by lazy, JIT, and generated serializers is an internal resolver-owned
operation. It remains valid after registration freezes and must not be treated as explicit
registration.
- Registration freeze does not disable native runtime type resolution. When class registration is
not required, native roots may discover an unregistered runtime class and materialize its
resolver-owned `TypeInfo`, descriptor, serializer, or JIT cache entry after freeze. This runtime
cache materialization must not create or change an explicit class, serializer, ID, name, or
policy registration.
- For GraalVM, use `fory codegen` to generate serializers when building native images. Do not add reflection configuration except for JDK `proxy`.
- In Java native mode (`xlang=false`), only `Types.BOOL` through `Types.STRING` share type IDs with xlang mode. Other native-mode type IDs differ.
- Choose one serializer ownership location per logical Java type family. Add native/xlang serializer variants only when the wire format or constructor contract truly differs.
Expand Down
13 changes: 13 additions & 0 deletions .agents/languages/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ Load this file when changing `javascript/`.
- Preserve generated serializer hot paths that bind writer, reader, ref, resolver, and metadata locals in outer closures; do not replace them with per-call context lookups without a measured reason.
- Do not add parallel header-low/header-high slot caches in TypeMeta hot paths to chase benchmark gaps. Header-cache hits must use the concrete checked cache owner directly; if a small hit hint is needed, cache TypeMeta objects themselves and compare `TypeMeta.headerHash`, not separate low/high header fields or benchmark-pattern state.
- JavaScript TypeMeta header cache hits should compare the 52-bit TypeMeta header hash directly. The hash is precise in JS `Number` and already includes the low header bits as hash input; do not add extra low-bit fields, sentinel state, nullable accepted headers, or parallel slot arrays around it.
- JavaScript `Fory` owns the one authoritative registration-frozen flag. The first root
serialization or deserialization sets it before codec work and leaves it set after failure.
`TypeResolver` owns registration maps, not a second lifecycle flag.
- Codegen hooks can start a root while an explicit registration graph is being generated. Recheck
the `Fory`-owned flag before every later serializer publication in that graph; do not add a
lifecycle flag to `TypeResolver`, stage the graph, or roll registry entries back.
- A failed root releases its operation-local reference and metadata state before the exception
escapes. The next root entry releases state retained by the previous successful operation before
reusing the context. Keep the successful root exit allocation-free and do not copy Java
backing-array retention policies onto native JavaScript arrays. Read-side metadata
occurrence arrays use native replacement reset. The MetaString and TypeMeta writer owner tables each have
their own logical size: reset active owner IDs and that table's logical size without clearing
bounded backing, and replace either backing only after its root has more than 8192 owners.
- Runtime value carriers such as decimal or reduced-precision numeric types belong under the core `types/` ownership boundary, with imports, exports, and codegen externals updated together.
- Keep `TypeInfo` as schema metadata. Compatibility-sensitive decisions belong on `TypeResolver` or explicit operations, not as retained resolver state on metadata objects.
- Normalize optional boolean config values at config construction; do not carry `null` through runtime paths when it means `false`.
Expand Down
9 changes: 9 additions & 0 deletions .agents/languages/kotlin.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ Load this file when changing `kotlin/` or compiler code that generates Kotlin so
Fory. Do not auto-install a new serializer for an existing type-registered Kotlin class unless the
wire format matches the previous serializer family and old-payload/new-runtime compatibility is
tested.
- Kotlin registration extensions target `BaseFory` so direct and thread-safe facades share the same
pre-root registration API, including module installation. Complete thread-safe facade
registration before concurrent serialization, deserialization, copy, or execution begins.
- Explicit type, serializer, enum, and union registration checks the receiving `BaseFory` facade or
natural registry owner's one frozen flag before mutation. Keep generated serializer construction
on the existing direct resolver path; do not add a parallel registration path or lifecycle state.
- Combined generated structural registration attaches the serializer with `setSerializer` after
registering the canonical STRUCT `TypeInfo`; `registerSerializer` would incorrectly reclassify
that wire identity as EXT. Generated unions use `registerUnion`.
- When adding Kotlin gRPC service companions, emit Kotlin source only. Reuse the generated schema
module's `ThreadSafeFory` and KSP-generated schema serializers, and keep grpc-java/grpc-kotlin
dependencies application-owned instead of adding them as hard `fory-kotlin` dependencies.
Expand Down
20 changes: 20 additions & 0 deletions .agents/languages/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ Load this file when changing `python/`, Cython serialization, or Python xlang be
- Python mode is the pure-Python xlang implementation and is mainly for debugging and testing.
- Cython mode is the default high-performance implementation.
- Cython mode owns the hot runtime path. Do not duplicate core runtime types between Python and Cython, tunnel Python facade methods into hidden Cython internals, or keep dead shims unless the user explicitly needs a compatibility module path.
- A direct Python `TypeResolver` owns one authoritative `_registry_frozen` flag. In Cython mode the
compiled `TypeResolver` is the active owner instead, and the Python resolver delegates explicit
registration checks to that compiled flag; do not mirror the flag between the two resolvers.
Roots set their active owner before codec work and never clear it, including after failure.
`ThreadSafeFory` owns its own `_registry_frozen` flag for the public registration boundary over
pooled children. Its existing callback list configures newly created children; it is not another
lifecycle state.
- Explicit type, serializer, name, and ID registration checks the frozen flag before mutation.
Automatic IDs remain registration-owned and must not turn native runtime discovery into explicit
registration.
- A Python wire name or user ID identifies one `TypeInfo`. Reject explicit or native-discovery
collisions before publishing resolver maps. Lazy TypeDef completion preserves a configured
serializer, does not retain partial state, and restores the prior serializer and TypeDef after
failed completion without adding a lifecycle state.
- Registry freeze prohibits explicit type and serializer registration after the first root; it
does not prohibit native runtime type resolution. Non-strict native writes may discover runtime
classes or callables, and reads may resolve those authorized by the deserialization policy. Both
paths may materialize resolver-owned type information or serializer cache entries without
creating or changing an explicit type, serializer, ID, name, or policy registration. Do not
describe these operations as late registration.
- Use explicit Cython fields and methods for fixed hot-path shapes. Avoid `__getattr__`, generic `object` fields, public bridge internals, or `Fory` backreferences where ownership can stay explicit.
- Keep Python and Cython context/ref-tracking branch conditions and stack mutations semantically aligned unless a documented intentional difference exists.
- Root deserialization graph memory budget state belongs to pure-Python and Cython `ReadContext`.
Expand Down
9 changes: 9 additions & 0 deletions .agents/languages/scala.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ Load this file when changing `scala/`.
- Scala supports the JVM and GraalVM Native Image, not Android. Do not add Android-specific Scala
sources, tests, resources, R8 metadata, compiler plugins, macros, dependencies, or compatibility
design.
- Scala registration extensions target `BaseFory` so direct and thread-safe facades share the same
pre-root registration API, including module installation. Complete thread-safe facade
registration before concurrent serialization, deserialization, copy, or execution begins.
- Explicit type, serializer, enum, and union registration checks the receiving `BaseFory` facade or
natural registry owner's one frozen flag before mutation. Keep generated serializer construction
on the existing direct resolver path; do not add a parallel registration path or lifecycle state.
- Combined generated structural registration attaches the serializer with `setSerializer` after
registering the canonical STRUCT `TypeInfo`; `registerSerializer` would incorrectly reclassify
that wire identity as EXT. Generated unions use `registerUnion`.

## Commands

Expand Down
Loading
Loading