Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
341 commits
Select commit Hold shift + click to select a range
309e458
Resolve F105: holder gains the acquiring-thread field
andrii0lomakin Jun 12, 2026
d9bb1a6
Resolve F109: promote-only-on-success + record isolation
andrii0lomakin Jun 12, 2026
2a3e505
Resolve F106: name the heal-exclusion properties
andrii0lomakin Jun 12, 2026
934b962
Resolve F107: sweep residual thread-owned-lock language
andrii0lomakin Jun 12, 2026
66bb1cf
Resolve F108: pin the gate inside the freezer wake loop
andrii0lomakin Jun 12, 2026
29cf38d
Resolve F110: relabel the promote class generator-context-first
andrii0lomakin Jun 12, 2026
93637de
Resolve F111: parse the actual gzip header length
andrii0lomakin Jun 12, 2026
6ae9258
Resolve F112: state the ack-gate reach, add restore rule
andrii0lomakin Jun 12, 2026
dcd2331
Resolve F113: add the error-capture liveness control
andrii0lomakin Jun 12, 2026
3a20dc7
Run adversarial pass 12 (scoped), register F114-F121
andrii0lomakin Jun 12, 2026
dcf9798
Migrate decision log to canonical research-log
andrii0lomakin Jun 15, 2026
3cc21fc
Resolve F114: wake parked commit on freeze layering
andrii0lomakin Jun 15, 2026
74666c8
Resolve F115: foreign heal reads the holder
andrii0lomakin Jun 15, 2026
f72a299
Resolve F116: checkOpenness cap is best-effort
andrii0lomakin Jun 15, 2026
58679df
Resolve F117: uniform warn-noop at release site
andrii0lomakin Jun 15, 2026
7338fbb
Resolve F118: context-exact promote classifier
andrii0lomakin Jun 15, 2026
b7588a1
Resolve F119: keep the suppression discipline
andrii0lomakin Jun 15, 2026
126908f
Resolve F120: bound the per-record buffer
andrii0lomakin Jun 15, 2026
2610c88
Resolve F121: route the sentinel by category
andrii0lomakin Jun 15, 2026
dd538d6
Mark pass 12 findings settled in gate record
andrii0lomakin Jun 15, 2026
3f345c6
Run adversarial pass 13 (scoped), register F122-F129
andrii0lomakin Jun 15, 2026
0ec0bf4
Resolve F122: kind-aware park-decision check
andrii0lomakin Jun 15, 2026
9a8dcde
Consolidate findings into invariant+test list
andrii0lomakin Jun 15, 2026
300bcf0
Add research-log adversarial gate review (iter 1)
andrii0lomakin Jun 15, 2026
ef358ad
Address gate iter-1 findings: I-A7, I-A1 drop, F51
andrii0lomakin Jun 15, 2026
f80f013
Address gate iter-2 finding A4: I-P2 positive coverage
andrii0lomakin Jun 15, 2026
32e3f1f
Clear Phase-0->1 adversarial gate (iter-3 PASS)
andrii0lomakin Jun 15, 2026
096f5d9
Add initial design
andrii0lomakin Jun 15, 2026
3ce2cf2
Pause Phase 1 for review — write handoff
andrii0lomakin Jun 15, 2026
62e980e
Queue two Phase-1 review-hold clarifications
andrii0lomakin Jun 15, 2026
a32d17a
Queue two Part-3 review-hold clarifications
andrii0lomakin Jun 16, 2026
d8d5c87
Apply Phase-1 review-hold clarifications to design.md
andrii0lomakin Jun 16, 2026
36c74f0
Schedule readability-feedback pass for next session
andrii0lomakin Jun 16, 2026
425c6eb
Apply cold-author readability pass to design.md (Mutation 3)
andrii0lomakin Jun 16, 2026
a3b25b6
Refine handoff for code-grounded readability pass-2
andrii0lomakin Jun 16, 2026
a1589cf
Apply code-grounded readability pass-2 to design.md (Mutation 4)
andrii0lomakin Jun 16, 2026
f5200bb
Resolve planning handoff: readability pass-2 landed, draft PR #1150 o…
andrii0lomakin Jun 16, 2026
26a2c30
Add initial implementation plan
andrii0lomakin Jun 16, 2026
229a627
Plan review autonomous fixes for transactional-schema
andrii0lomakin Jun 16, 2026
3d4c20e
Phase A review and decomposition for Track 1
andrii0lomakin Jun 16, 2026
4ee62e4
Record Phase B base commit for Track 1
andrii0lomakin Jun 16, 2026
511d862
Recover lazily from a missing file during WAL replay
andrii0lomakin Jun 16, 2026
77876b3
Record step-level review files for Track 1 Step 1 (iter 1)
andrii0lomakin Jun 16, 2026
88feabf
Review fix: strengthen replay regression assertions and document cons…
andrii0lomakin Jun 16, 2026
6278783
Record episode for Track 1 Step 1 (WAL replay lazy-consult fix)
andrii0lomakin Jun 16, 2026
77ccbfe
Mark Track 1 complete
andrii0lomakin Jun 16, 2026
beee0c6
Apply pre-flight amendments before Track 2
andrii0lomakin Jun 16, 2026
cb2fe26
Phase A review and decomposition for Track 2
andrii0lomakin Jun 16, 2026
ee694ea
Record Phase B base commit for Track 2
andrii0lomakin Jun 16, 2026
0ad368e
Split schema into per-class records
andrii0lomakin Jun 16, 2026
efdf960
Review fix: self-heal stale schema record ids and harden round-trip t…
andrii0lomakin Jun 16, 2026
4aee217
Record episode for Track 2 Step 1 (per-class schema records)
andrii0lomakin Jun 16, 2026
b5a152e
Review fix: drop redundant read lock in schema toStream
andrii0lomakin Jun 17, 2026
51ffa08
Mark Track 2 complete
andrii0lomakin Jun 17, 2026
0d9bf16
Apply pre-flight amendments before Track 3
andrii0lomakin Jun 17, 2026
350c3ad
Record Track 3 Phase A risk review (iter 1)
andrii0lomakin Jun 17, 2026
eb8da16
Record Track 3 Phase A technical + adversarial reviews (iter 1)
andrii0lomakin Jun 17, 2026
f0d3cd5
Phase A review and decomposition for Track 3
andrii0lomakin Jun 17, 2026
e86b048
Record Phase B base commit for Track 3
andrii0lomakin Jun 17, 2026
7d656b5
Add tx-local schema copy foundation
andrii0lomakin Jun 17, 2026
beba5eb
Review fix: make tx-local schema seed read-only
andrii0lomakin Jun 17, 2026
6e575d3
Record episode for Track 3 Step 1 (tx-local schema copy foundation)
andrii0lomakin Jun 17, 2026
8686653
Route schema proxies through a tx-local resolve seam
andrii0lomakin Jun 17, 2026
040a575
Review fix: keep argument-taking subclass reads total
andrii0lomakin Jun 17, 2026
dc8cd28
Record episode for Track 3 Step 2 (proxy routing seam)
andrii0lomakin Jun 17, 2026
cf21ff9
De-guard schema and index mutation entry points
andrii0lomakin Jun 17, 2026
3d77845
Review fix: make tx-deferred index handle safe on public path
andrii0lomakin Jun 17, 2026
b5ee77b
Record episode for Track 3 Step 3 (de-guard mutation entry points)
andrii0lomakin Jun 17, 2026
e8f30f7
Add metadata-write mutex with engage and release
andrii0lomakin Jun 17, 2026
5eaf9f2
Review fix: harden mutex engage/seed and prove blocking deterministic…
andrii0lomakin Jun 17, 2026
6883045
Record episode for Track 3 Step 4 (metadata-write mutex); Phase B com…
andrii0lomakin Jun 17, 2026
8fadfc0
Workflow: normalize Track 3 step-1 review filenames to -step1- conven…
andrii0lomakin Jun 17, 2026
2152c5b
Review fix: guard tx-schema seed against re-entrant mutex engage
andrii0lomakin Jun 17, 2026
1b28051
Workflow: record Track 3 Phase C review iteration 1 (1/3)
andrii0lomakin Jun 17, 2026
2422142
Review fix: harden mutex release, deferred-handle reads, and de-guard…
andrii0lomakin Jun 17, 2026
035f3d8
Workflow: record Track 3 Phase C review iteration 2 (2/3)
andrii0lomakin Jun 17, 2026
b619438
Pause Phase C Track 3 for new session — write handoff
andrii0lomakin Jun 25, 2026
db1880f
Review fix: record tx-local create/rename; correct mutex Javadoc
andrii0lomakin Jun 25, 2026
eae1453
Mark Track 3 complete
andrii0lomakin Jun 25, 2026
7ed8916
Workflow: commit Track 3 Phase C iteration-1 review files
andrii0lomakin Jun 25, 2026
cea97d4
Apply pre-flight amendments before Track 4
andrii0lomakin Jun 26, 2026
fbe7d07
Phase A review and decomposition for Track 4
andrii0lomakin Jun 26, 2026
04efe8d
Record Phase B base commit for Track 4
andrii0lomakin Jun 26, 2026
7cb58c0
Extract lock-free commit-window storage primitives
andrii0lomakin Jun 26, 2026
32e0853
Review fix: bound lock-free resolver test, correct seam Javadoc
andrii0lomakin Jun 26, 2026
3b7f21d
Record episode for Track 4 Step 1 (lock-free commit-window primitives)
andrii0lomakin Jun 26, 2026
07fc1f3
Re-decompose Track 4: split D2 provisional-id production into a new step
andrii0lomakin Jun 26, 2026
c45094c
Allocate provisional collection ids for in-tx class create
andrii0lomakin Jun 26, 2026
b2a95a5
Review fix: invert tx-local setAbstract(false) collection allocation
andrii0lomakin Jun 26, 2026
b8ff1aa
Record episode for Track 4 Step 2 (D2 provisional-id production)
andrii0lomakin Jun 26, 2026
0c782c4
Re-decompose Track 4: split lock-free commit-window record-read subst…
andrii0lomakin Jun 26, 2026
801c8a8
Add lock-free commit-window record-read substrate
andrii0lomakin Jun 26, 2026
b6a0fe1
Review fix: harden commit-window exit + test leak hazard
andrii0lomakin Jun 26, 2026
2347f38
Record episode for Track 4 Step 3 (lock-free commit-window read subst…
andrii0lomakin Jun 26, 2026
7fe189a
Record Track 4 Step 3 step-level review files
andrii0lomakin Jun 26, 2026
491aca3
Reconcile schema structure at commit
andrii0lomakin Jun 29, 2026
a05cb65
Review fix: symmetrize commit-time collection drop + undo
andrii0lomakin Jun 29, 2026
9778c0c
Review fix: revert created-collection structure on failed schema commit
andrii0lomakin Jun 29, 2026
00d0286
Record episode for Track 4 Step 4 (commit-time reconciliation core)
andrii0lomakin Jun 29, 2026
30d8dff
Record Track 4 Step 4 step-level review files
andrii0lomakin Jun 29, 2026
9b1e5a8
Write only changed schema records at commit
andrii0lomakin Jun 29, 2026
07a0884
Review fix: record tx-local class writes at the proxy choke point
andrii0lomakin Jun 29, 2026
545cc86
Record episode for Track 4 Step 5 (selective per-class write + F59 gu…
andrii0lomakin Jun 29, 2026
c29d381
Record Track 4 Step 5 step-level review files
andrii0lomakin Jun 29, 2026
cfd22ed
Convert two hot schema reads to snapshot-first
andrii0lomakin Jun 29, 2026
95b09ff
Record episode for Track 4 Step 6 (two hot reads to snapshot-first)
andrii0lomakin Jun 29, 2026
1da2e70
Record Track 4 Step 6 step-level review files
andrii0lomakin Jun 29, 2026
575cb3d
Record Track 4 Phase C track-level review files (iteration 1)
andrii0lomakin Jun 30, 2026
d271b8c
Review fix: stop rename over-marking, harden schema commit
andrii0lomakin Jun 30, 2026
8440f10
Workflow: record Track 4 Phase C review iteration 1 (1/3)
andrii0lomakin Jun 30, 2026
9659a56
Review fix: add committed tests for alter, property, and cross-class …
andrii0lomakin Jun 30, 2026
97507bf
Workflow: record Track 4 Phase C review iteration 2 (2/3)
andrii0lomakin Jun 30, 2026
e6e0192
Apply plan corrections from Track 4 review
andrii0lomakin Jun 30, 2026
812a3d5
Workflow: Track 4 Phase C review complete (code review [x])
andrii0lomakin Jun 30, 2026
d147a53
Pause Track 4 Phase C for next session — write handoff
andrii0lomakin Jun 30, 2026
2953a98
Apply plan corrections from Track 4 review
andrii0lomakin Jun 30, 2026
80449c1
Apply plan corrections from Track 4 review
andrii0lomakin Jun 30, 2026
4543808
Resume Phase C: apply review-mode fixes, defer escalation
andrii0lomakin Jun 30, 2026
1329b65
Review fix: harden barrier-hang tests, tighten rename rationale, loud…
andrii0lomakin Jun 30, 2026
815351d
Pause Track 4 Phase C: escalate validation gap next session
andrii0lomakin Jun 30, 2026
58081f2
Resume Phase C: drain handoff, route validation gap to inline replanning
andrii0lomakin Jun 30, 2026
241dcee
Inline replan after Track 4: tx-aware snapshot (D21)
andrii0lomakin Jun 30, 2026
9aecb1d
Plan review autonomous fixes for transactional-schema (post-D21 replan)
andrii0lomakin Jun 30, 2026
5d6a6b1
Mark Track 4 complete
andrii0lomakin Jul 1, 2026
e7d1c07
Apply pre-flight amendments before Track 5
andrii0lomakin Jul 1, 2026
11a5a80
Phase A review and decomposition for Track 5
andrii0lomakin Jul 1, 2026
ff45cba
Record Phase B base commit for Track 5
andrii0lomakin Jul 1, 2026
0e39d9e
Add tx-local index overlay and query-side resolution
andrii0lomakin Jul 1, 2026
85a981a
Review fix: memoize overlay snapshot, soften overstated comments
andrii0lomakin Jul 1, 2026
aedc902
Record episode for Track 5 Step 1 (tx-local index overlay)
andrii0lomakin Jul 1, 2026
712384f
Build and drop tx index engines at commit
andrii0lomakin Jul 1, 2026
623d8c8
Review fix: harden commit-time index engine lifecycle
andrii0lomakin Jul 1, 2026
9e3aace
Record episode for Track 5 Step 2 (commit-time engine lifecycle)
andrii0lomakin Jul 1, 2026
4cbe5bb
Split Track 5 roster into 4 steps
andrii0lomakin Jul 2, 2026
008e0dc
Make the immutable schema snapshot tx-aware
andrii0lomakin Jul 2, 2026
ecdd78b
Review fix: make schema version process-unique
andrii0lomakin Jul 2, 2026
8f6b60b
Record episode for Track 5 Step 3 (tx-aware snapshot)
andrii0lomakin Jul 2, 2026
41757cf
Carry provisional collection ids in RIDs
andrii0lomakin Jul 2, 2026
9152db8
Review fix: harden provisional-id commit boundary
andrii0lomakin Jul 2, 2026
fea2419
Record episode for Track 5 Step 4 (provisional-id-in-RID)
andrii0lomakin Jul 2, 2026
c777573
Add Track 5 track-level review files (iteration 1, 8 of 9 dims)
andrii0lomakin Jul 2, 2026
55a8d81
Add Track 5 test-behavior track-level review file (iteration 1)
andrii0lomakin Jul 2, 2026
a1820bc
Review fix: harden index-commit failure paths
andrii0lomakin Jul 2, 2026
2ae6d17
Record Track 5 review iteration 1 in Progress
andrii0lomakin Jul 2, 2026
3943299
Review fix: tighten commit path and test precision
andrii0lomakin Jul 2, 2026
48712a8
Record Track 5 review iteration 2 in Progress
andrii0lomakin Jul 2, 2026
022542b
Mark Track 5 track-level code review complete
andrii0lomakin Jul 2, 2026
227b8a8
Record Track 5 track-review outcomes
andrii0lomakin Jul 2, 2026
95e5139
Pause Phase C for track-completion review — write handoff
andrii0lomakin Jul 2, 2026
d21b412
Fix Track 5 findings D-A/D-B in tx index path
andrii0lomakin Jul 14, 2026
a0d2a8d
Fix review findings BG101/CN101 on D-A/D-B
andrii0lomakin Jul 14, 2026
3c8346f
Apply Track 5 user-review observations OBS-1..OBS-9a
andrii0lomakin Jul 16, 2026
04f1688
Fix review findings BG103/BG104/CQ103 on OBS batch
andrii0lomakin Jul 16, 2026
09a7e8b
Track 05 complete: tx-index-overlay
andrii0lomakin Jul 16, 2026
a64d751
Generate collection names from counter alone (D11)
andrii0lomakin Jul 16, 2026
196ce67
Add persisted engine fileBaseId and HWM allocator
andrii0lomakin Jul 16, 2026
9ee357d
Key engine files by ie_<fileBaseId> stems (D16)
andrii0lomakin Jul 16, 2026
a5dc209
Fix D16 review findings (CS-101, CS-104 family)
andrii0lomakin Jul 16, 2026
b27d46e
Re-associate class indexes on rename (D17)
andrii0lomakin Jul 16, 2026
a37d495
Fix D17 review findings (BG107-109, CN109/110)
andrii0lomakin Jul 16, 2026
3e9c542
Drop class indexes on tx-local dropClass
andrii0lomakin Jul 17, 2026
27104e6
Polish tx dropClass index-drop docs and tests
andrii0lomakin Jul 17, 2026
91f053a
Overlay-route DROP INDEX existence check and DROP *
andrii0lomakin Jul 17, 2026
dd51de6
Overlay-route getClassIndex
andrii0lomakin Jul 17, 2026
7d26fab
Fix OBS-11 review findings (BG-112/113, TQ-113/114)
andrii0lomakin Jul 17, 2026
531673a
Apply Track 6 user-review observations: fold guards and comment fixes
andrii0lomakin Jul 20, 2026
3272d8d
Strip ephemeral workflow identifiers from comments
andrii0lomakin Jul 20, 2026
70b329b
Polish observation batch: remove-side guard symmetry and comment reflow
andrii0lomakin Jul 20, 2026
218288c
Track 06 complete: base-keyed-engine-files
andrii0lomakin Jul 20, 2026
998d9a1
Fix stale schema seed and failed-commit undo paths
andrii0lomakin Jul 21, 2026
df82520
Record Track 7 Step 1 episode and design artifacts
andrii0lomakin Jul 21, 2026
3a62b67
Guard schema reload against tx-local seeding
andrii0lomakin Jul 21, 2026
75aae6a
Record Track 7 Step 2 episode
andrii0lomakin Jul 21, 2026
0a8ddaa
Harden failed-commit undo and commit-time schema reads
andrii0lomakin Jul 21, 2026
f1c1842
Record Track 7 Step 1 review-fix episode
andrii0lomakin Jul 21, 2026
d9d3875
Update IT file lookups for counter-only collection names
andrii0lomakin Jul 22, 2026
af2a089
Record resolution of the four rename-fallout ITs
andrii0lomakin Jul 22, 2026
5bf22a9
Restore link-bag registration in failed-commit undo
andrii0lomakin Jul 22, 2026
8d99ae9
Record crash-safety review-fix episode for Track 7
andrii0lomakin Jul 22, 2026
1b5ee8a
Harden metadata-write mutex lifecycle handshake
andrii0lomakin Jul 22, 2026
fb2d35c
Record Track 7 Step 3 episode
andrii0lomakin Jul 22, 2026
b9e4f99
Add abort-predicate write acquisition to ScalableRWLock
andrii0lomakin Jul 22, 2026
c8d377b
Record Track 7 Step 4 episode and review artifacts
andrii0lomakin Jul 22, 2026
4714611
Close teardown races in the mutex handshake
andrii0lomakin Jul 22, 2026
70179e1
Record Track 7 Step 3 review-fix episode
andrii0lomakin Jul 22, 2026
891960b
Harden abort-predicate lock against throwing predicates
andrii0lomakin Jul 22, 2026
ed8fc33
Record Track 7 Step 4 review-fix episode and review artifacts
andrii0lomakin Jul 22, 2026
6a10dba
Gate schema commits against operator freezes
andrii0lomakin Jul 23, 2026
5dd5f8f
Record Track 7 Step 5 episode and review artifacts
andrii0lomakin Jul 23, 2026
b67f45c
Close freezer bookkeeping leak and pin the gate mechanisms
andrii0lomakin Jul 23, 2026
6fffa62
Record Track 7 Step 5 review-fix episode and review artifacts
andrii0lomakin Jul 23, 2026
e352d98
Pin deterministic throw for cut-woken parked data commits
andrii0lomakin Jul 23, 2026
83474c9
Record the BG8 resolution in the Track 7 plan
andrii0lomakin Jul 23, 2026
49fa1c9
Record Track 7 cumulative review and Step 5 gate artifacts
andrii0lomakin Jul 23, 2026
71484af
Strip ephemeral workflow IDs and pin freeze-arm premise in Track 7 code
andrii0lomakin Jul 23, 2026
5b40f2f
Record Track 7 closeout gate verification report
andrii0lomakin Jul 23, 2026
23b0454
Track 07 complete: concurrency hardening
andrii0lomakin Jul 23, 2026
6d5b0f3
Draft Track 8 design (genesis and migration) for review
andrii0lomakin Jul 23, 2026
8407e21
Record Track 8 design rulings
andrii0lomakin Jul 23, 2026
d7daa64
Record Track 8 adversarial pass-1 review reports
andrii0lomakin Jul 23, 2026
488cda6
Amend Track 8 design per adversarial pass-1 triage
andrii0lomakin Jul 23, 2026
0a8c125
Record Track 8 design gate verification reports
andrii0lomakin Jul 23, 2026
dca0ebc
Micro-amend Track 8 design per gate suggestions
andrii0lomakin Jul 23, 2026
babb331
Decompose Track 8 into implementation steps
andrii0lomakin Jul 23, 2026
8d67ebf
Record Track 8 decomposition approval
andrii0lomakin Jul 23, 2026
61bc975
Embed blob collections into storage creation
andrii0lomakin Jul 23, 2026
dd1e4c8
Record Track 8 Step 1 completion
andrii0lomakin Jul 23, 2026
962d242
Apply Track 8 Step 1 review fixes
andrii0lomakin Jul 23, 2026
bbd991e
Record Track 8 Step 1 review-fix iteration 1
andrii0lomakin Jul 23, 2026
a9b3d17
Record Track 8 Step 1 review artifacts and fix stale seam note
andrii0lomakin Jul 23, 2026
734c603
Persist bootstrap-valid empty-schema root at creation
andrii0lomakin Jul 24, 2026
b8ed384
Record Track 8 Step 2 completion
andrii0lomakin Jul 24, 2026
40dfd45
Apply Track 8 Step 2 review fixes
andrii0lomakin Jul 24, 2026
1b083be
Record Track 8 Step 2 review-fix iteration 1
andrii0lomakin Jul 24, 2026
31fe800
Record Track 8 Step 2 review artifacts and thread CQ15 obligation
andrii0lomakin Jul 24, 2026
44d32c2
Restructure genesis into two phases with failure containment
andrii0lomakin Jul 24, 2026
d30450d
Record Track 8 Step 3 completion
andrii0lomakin Jul 24, 2026
2a4ddd6
Apply Track 8 Step 3 review fixes
andrii0lomakin Jul 24, 2026
1ceab2c
Record Track 8 Step 3 review-fix iteration 1
andrii0lomakin Jul 24, 2026
71a99ec
Record Track 8 Step 3 review artifacts and gate residual amendments
andrii0lomakin Jul 24, 2026
1c74dbf
Harden database export and add validated-gzip primitive
andrii0lomakin Jul 24, 2026
927f015
Record Track 8 Step 4 completion
andrii0lomakin Jul 24, 2026
0ecda99
Apply Track 8 Step 4 review fixes
andrii0lomakin Jul 24, 2026
0bc28cb
Record Track 8 Step 4 review-fix iteration 1
andrii0lomakin Jul 24, 2026
d700578
Record Track 8 Step 4 review artifacts
andrii0lomakin Jul 24, 2026
fec5fad
Harden import: pre-flight deferral, v15 strictness
andrii0lomakin Jul 25, 2026
ee554fc
Record Track 8 Step 5 in the track file
andrii0lomakin Jul 25, 2026
17d488b
Fix Step 5 review findings: version latch, clusters alias, long manif…
andrii0lomakin Jul 25, 2026
828d63e
Record Track 8 Step 5 review artifacts and iteration 1
andrii0lomakin Jul 25, 2026
49e181d
Validate dump info fields and add migration runbook
andrii0lomakin Jul 25, 2026
b25bdbc
Record Track 8 Step 6 in the track file
andrii0lomakin Jul 25, 2026
28ca29f
Fix Step 6 review findings: runbook surface, marker parse, EOF bounds…
andrii0lomakin Jul 25, 2026
62fb6a7
Record Track 8 Step 6 review-fix iteration 1
andrii0lomakin Jul 25, 2026
11a5b2c
Record Track 8 Step 6 review artifacts and gate result
andrii0lomakin Jul 25, 2026
8876537
Fix cumulative review findings: snapshot accessors, EOF bounds, fstat…
andrii0lomakin Jul 25, 2026
cb28c61
Record Track 8 cumulative review-fix iteration 1
andrii0lomakin Jul 25, 2026
220a18b
Make dump truncation loud on the legacy schema path
andrii0lomakin Jul 25, 2026
646d09c
Record cumulative-iteration gate PASS and RG fixes
andrii0lomakin Jul 25, 2026
53d9c71
Record Track 8 cumulative review artifacts and close the track-level …
andrii0lomakin Jul 25, 2026
11da4f7
Track 08 complete: genesis and schema migration
andrii0lomakin Jul 27, 2026
c8849f9
Add final design document
andrii0lomakin Jul 27, 2026
46ce887
Add architecture decision record
andrii0lomakin Jul 27, 2026
7ea843c
Fix review findings in the two final artifacts
andrii0lomakin Jul 27, 2026
068ef44
Align adr.md with the design-final corrections
andrii0lomakin Jul 27, 2026
8edf95e
Align the D6 footer gloss with the three-channel marking text
andrii0lomakin Jul 27, 2026
44d2d96
Relocate the final artifacts to the ADR archive
andrii0lomakin Jul 27, 2026
d409e96
Remove workflow scaffolding
andrii0lomakin Jul 27, 2026
7dd4363
Fix schema/index-manager ABBA lock inversion
andrii0lomakin Jul 28, 2026
1e23a7a
Harden lock-order fix per baseline review
andrii0lomakin Jul 28, 2026
e8a034d
Record the lock-order guard and ordering limits in the ADR
andrii0lomakin Jul 28, 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
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ public enum GlobalConfiguration {
"Amount storage collections allocated for storing blobs", Integer.class,
8),

EXPORT_RECORD_SPILL_THRESHOLD("youtrackdb.export.recordSpillThreshold",
"Size in bytes above which a single record's JSON rendering spills from memory to a"
+ " transient file during database export. Bounds the export's memory use; an"
+ " oversized-but-healthy record is still exported whole, never shed. Operational"
+ " tuning, not correctness.",
Integer.class,
32 * 1024 * 1024),

STORAGE_SNAPSHOT_INDEX_CLEANUP_THRESHOLD(
"youtrackdb.storage.snapshotIndex.cleanupThreshold",
"Number of entries in the shared snapshot index that triggers GC of stale entries",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*/
package com.jetbrains.youtrackdb.internal.common.concur.lock;

import com.jetbrains.youtrackdb.internal.core.exception.BaseException;
import com.jetbrains.youtrackdb.internal.core.exception.DatabaseException;
import java.lang.ref.Cleaner;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
Expand All @@ -32,6 +34,7 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.StampedLock;
import java.util.function.BooleanSupplier;

/**
* <h1>Scalable Read-Write Lock </h1>
Expand Down Expand Up @@ -275,6 +278,17 @@ public Lock writeLock() {
return writerLock;
}

/**
* Whether the exclusive (write) lock is currently held by some thread. The underlying
* {@link StampedLock} tracks no owner, so this cannot distinguish the current thread from
* another holder; it exists for assertions that a code path runs inside an exclusive-lock
* window (a caller that must itself hold the lock cannot be foiled by another holder anyway,
* because that holder would have blocked it).
*/
public boolean isWriteLocked() {
return stampedLock.isWriteLocked();
}

/**
* Creates a new ReadersEntry instance for the current thread and its associated AtomicInteger to
* store the state of the Reader
Expand Down Expand Up @@ -605,4 +619,148 @@ public boolean exclusiveTryLockNanos(long nanosTimeout) throws java.lang.Interru

return true;
}

/**
* Acquires the write lock ONCE with an abort predicate, for a waiter that must give way to an
* external condition (an operator freeze engaging) without ever spuriously failing on
* contention alone.
*
* <p>The two-guarantee contract this primitive exists for (both load-bearing for the freezer
* gate's third checkpoint; see the correctness comments inline):
*
* <ul>
* <li><b>Bounded acquisition under sustained readers.</b> The write bit is acquired exactly
* once and then HELD through the reader drain — writer preference: from the moment the
* bit is set, new readers observe {@code isWriteLocked()} and back off exactly as they do
* against {@link #exclusiveLock()}. There is no inter-attempt release window (unlike an
* {@link #exclusiveTryLockNanos} retry loop, which releases the bit on every drain
* timeout and forfeits admission to slip-in readers), so the acquisition completes within
* the maximum residual reader residence — deterministic, no starvation, no retry storm.
* <li><b>Abort within one poll granularity.</b> The predicate is polled between phase-1
* {@code tryWriteLock} attempts (each bounded by {@code pollNanos}) and on every yield
* iteration of the phase-2 reader-drain spin (the tightest granularity available; the
* intended predicate is a single atomic-counter read, so per-iteration polling costs
* less than the yield beside it). On abort the write bit is released fully — no queue
* entry, no held bit, no residual writer-intent state — so no reader or writer is
* stranded (parked readers spin on {@code isWriteLocked()} and proceed; there is no
* wait/notify channel to lose a wakeup on) and the primitive is immediately reusable.
* </ul>
*
* <p>The predicate is additionally re-checked immediately after the drain completes (which is
* also immediately after bit acquisition when there are no residual readers to drain), BEFORE
* returning {@code true}: a condition arriving exactly at the acquisition-success edge aborts
* here rather than being missed and caught only by later downstream gates with the lock held.
*
* <p>No new deadlock edge: the method blocks only on the same two waits {@link #exclusiveLock()}
* already performs (the stamped writer queue and the reader-drain spin), both now bounded by the
* abort predicate; the abort path releases everything before returning, and a queued phase-1
* candidate holds nothing at all (readers never consult the stamped writer queue — they poll
* only {@code isWriteLocked()}).
*
* <p>Interruption: an interrupt while parked in the phase-1 timed acquire restores the interrupt
* flag and throws {@link DatabaseException} naming the lock state. The phase-2 drain is a yield
* spin, uninterruptible exactly like {@link #exclusiveLock()}'s.
*
* <p>All other methods of this class are byte-for-byte unaffected; readers pay nothing new.
*
* <p>Fairness note: a phase-1 timeout re-enters the stamped writer queue at its tail, so under
* sustained contention from plain {@link #exclusiveLock()} writers this waiter can lose its
* queue position once per {@code pollNanos} — phase 1 is unbounded in theory under a permanent
* writer storm. Acceptable for the intended consumer (storage state locks have rare, short
* writers); a fairness-sensitive consumer would need a different phase-1 shape.
*
* <p>A predicate that THROWS is propagated — but never with the write bit held: a phase-1 throw
* happens with nothing acquired, and the phase-2 evaluation sites are guarded so the bit is
* released before the failure escapes (an ownerless write bit would wedge every reader and
* writer of this lock forever).
*
* @param abort polled condition; when it returns {@code true} the acquisition is abandoned
* and this method returns {@code false} with no lock state held. Must be cheap
* (it is polled per drain iteration) and must not itself touch this lock.
* @param pollNanos the phase-1 per-attempt park bound; also the coarsest abort-detection
* latency while queued against another writer. Must be positive.
* @return {@code true} when the write lock was acquired (caller releases via
* {@link #exclusiveUnlock()}); {@code false} when the abort predicate turned true first.
*/
public boolean exclusiveLockWithAbort(final BooleanSupplier abort, final long pollNanos) {
java.util.Objects.requireNonNull(abort, "abort predicate must not be null");
if (pollNanos <= 0) {
throw new IllegalArgumentException("pollNanos must be positive, got " + pollNanos);
}
// Phase 1: queue against writers only. A parked tryWriteLock candidate blocks no readers:
// readers poll isWriteLocked(), which stays false until an acquisition actually succeeds,
// so aborting from this phase leaves no trace at all.
long stamp = 0;
while (stamp == 0) {
if (abort.getAsBoolean()) {
return false;
}
try {
stamp = stampedLock.tryWriteLock(pollNanos, TimeUnit.NANOSECONDS);
} catch (final InterruptedException e) {
// Restore the flag and fail loudly naming the state: a swallowed interrupt would turn
// into an unbounded uninterruptible wait. The message stays generic (this is a shared
// primitive, not a storage-only one) and reports only what is certain: the write bit was
// not acquired by this call. The holder snapshot is best-effort — it can name a free lock
// when a pre-interrupted thread never actually parked (StampedLock checks the interrupt
// flag before attempting) or when the holder released concurrently.
Thread.currentThread().interrupt();
throw BaseException.wrapException(
new DatabaseException(
"interrupted while acquiring the write lock with an abort predicate (write bit"
+ " not acquired by this call; "
+ (stampedLock.isWriteLocked()
? "another writer currently holds the write bit"
: "no writer currently holds the write bit")
+ ")"),
e, (String) null);
}
}

// Phase 2: the write bit is HELD from here on — writer preference engaged exactly like
// exclusiveLock (new readers observe isWriteLocked() and back off). Drain the residual
// readers, polling the abort predicate on every yield iteration. The whole phase is guarded:
// a THROW from the predicate (or any phase-2 failure) must release the bit before
// propagating — an ownerless write bit would wedge every reader (spinning on isWriteLocked)
// and writer of this lock forever. No double-unlock is possible: the two abort branches
// below unlock and RETURN immediately, so any throw reaching the catch arrives with the bit
// still held.
try {
var localReadersStateArray = readersStateArrayRef.get();
if (localReadersStateArray == null) {
// Set to dummyArray before scanning the readersStateList to impose
// a linearizability condition
readersStateArrayRef.set(dummyArray);
// Copy readersStateList to an array
localReadersStateArray =
readersStateList.toArray(new AtomicInteger[readersStateList.size()]);
readersStateArrayRef.compareAndSet(dummyArray, localReadersStateArray);
}

for (var readerState : localReadersStateArray) {
while (readerState != null && readerState.get() == SRWL_STATE_READING) {
if (abort.getAsBoolean()) {
// Full release: the bit drops, backed-off readers spinning on isWriteLocked() proceed
// (no lost wakeup possible — there is no parking channel, only the polled bit), and
// the primitive is immediately reusable.
stampedLock.asWriteLock().unlock();
return false;
}
Thread.yield();
}
}

// Predicate re-check at the acquisition-success edge, before returning true. This closes
// the window where the condition arrives exactly as the drain completes — including the
// zero-residual-readers case, where the drain loop body never ran and so never polled.
if (abort.getAsBoolean()) {
stampedLock.asWriteLock().unlock();
return false;
}
return true;
} catch (final Throwable phaseTwoFailure) {
stampedLock.asWriteLock().unlock();
throw phaseTwoFailure;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.CopyOption;
import java.nio.file.FileSystems;
Expand All @@ -33,6 +34,7 @@
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Locale;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -161,8 +163,7 @@ public static void createDirectoryTree(final String iFileName) {
}
}

@Nullable
public static String getPath(final String iPath) {
@Nullable public static String getPath(final String iPath) {
if (iPath == null) {
return null;
}
Expand Down Expand Up @@ -318,4 +319,58 @@ public static void atomicMoveWithFallback(Path source, Path target, Object reque
Files.move(source, target);
}
}

/**
* Durably promotes {@code source} to {@code target} (the CS40 promote recipe of Track 8's
* export hardening): (1) the source file's content is fsynced through a freshly opened
* channel — the writing stream is already closed, so the sync needs its own channel; (2) the
* file is renamed with {@code ATOMIC_MOVE} + {@code REPLACE_EXISTING}, so a pre-existing
* target is replaced only by this whole, durable file and a crash can never leave a torn
* target; (3) the target's parent directory is fsynced (POSIX rename durability — without it
* a crash after the rename can lose the directory entry itself).
*
* <p>Deliberately FAIL-CLOSED: unlike {@link #atomicMoveWithFallback} there is NO regular-move
* fallback — a filesystem that cannot perform the atomic replace fails the promote rather
* than silently degrading to a copy that can tear the target. The parent-directory fsync
* carve-out is NARROW: only the directory-channel OPEN failure is tolerated (platforms like
* Windows cannot open directory channels, and the POSIX directory-entry hazard does not
* apply there in the same form); an I/O failure from {@code force(true)} on a successfully
* opened directory channel is a GENUINE fsync failure and propagates — reporting success
* over it would let a crash revert the rename after the caller already reported the promote
* durable.
*
* <p>Contract note: only the TARGET's parent directory is fsynced. The current callers move
* within a single directory (the export temp file sits next to its final name); a future
* CROSS-directory caller would additionally need the SOURCE's parent fsynced, or the
* source-entry removal may not be durable.
*/
public static void durableAtomicMove(Path source, Path target, Object requester)
throws IOException {
try (var channel = FileChannel.open(source, StandardOpenOption.WRITE)) {
channel.force(true);
}
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
final var parent = target.toAbsolutePath().getParent();
if (parent != null) {
FileChannel directoryChannel = null;
try {
directoryChannel = FileChannel.open(parent, StandardOpenOption.READ);
} catch (IOException e) {
// The documented platform carve-out: the directory cannot be opened as a channel
// (e.g. Windows). Only the OPEN failure is tolerated — see the javadoc.
LogManager.instance()
.warn(requester,
"Cannot open the parent directory of '%s' for fsync after the atomic move;"
+ " continuing (the platform does not support directory channels)",
e, target);
}
if (directoryChannel != null) {
// A failure from force(true) here is a genuine fsync failure and MUST propagate
// (fail-closed): the rename's durability cannot be vouched for.
try (var openedDirectoryChannel = directoryChannel) {
openedDirectoryChannel.force(true);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
public final class IndexEngineData {

private final int indexId;

/**
* The engine's stable file base id: a monotonically allocated, never-reused number that keys
* the engine's storage files (stem {@code ie_<fileBaseId>}). Unlike {@link #indexId} — a
* first-null-slot registry index that is deliberately reused after a drop or a failed commit —
* the file base id is unique for the storage's whole lifetime, so a drop-and-recreate of a
* same-named index can never collide on files, and an index rename never has to touch them.
* Allocated by the storage's high-water-mark allocator inside the creating atomic operation and
* persisted with the engine entry (engine-property binary version 2+).
*/
private final int fileBaseId;
@Nonnull
private final String name;
private final String algorithm;
Expand Down Expand Up @@ -39,6 +50,7 @@ public final class IndexEngineData {

public IndexEngineData(
int indexId,
int fileBaseId,
final IndexMetadata metadata,
final Boolean durableInNonTxMode,
final byte valueSerializerId,
Expand All @@ -49,6 +61,7 @@ public IndexEngineData(
final String encryptionOptions,
final Map<String, String> engineProperties) {
this.indexId = indexId;
this.fileBaseId = fileBaseId;
var definition = metadata.getIndexDefinition();
this.name = metadata.getName();
this.algorithm = metadata.getAlgorithm();
Expand All @@ -73,6 +86,7 @@ public IndexEngineData(

public IndexEngineData(
int indexId,
int fileBaseId,
@Nonnull final String name,
final String algorithm,
String indexType,
Expand All @@ -90,6 +104,7 @@ public IndexEngineData(
final String encryptionOptions,
final Map<String, String> engineProperties) {
this.indexId = indexId;
this.fileBaseId = fileBaseId;
this.name = name;
this.algorithm = algorithm;
this.indexType = indexType;
Expand All @@ -116,6 +131,13 @@ public int getIndexId() {
return indexId;
}

/**
* The engine's stable, never-reused file base id. See {@link #fileBaseId}.
*/
public int getFileBaseId() {
return fileBaseId;
}

public int getKeySize() {
return keySize;
}
Expand Down Expand Up @@ -175,8 +197,7 @@ public boolean isNullValuesSupport() {
return nullValuesSupport;
}

@Nullable
public Map<String, String> getEngineProperties() {
@Nullable public Map<String, String> getEngineProperties() {
if (engineProperties == null) {
return null;
}
Expand Down
Loading
Loading