diff --git a/app/application.ml b/app/application.ml index 9148c4b..714537b 100644 --- a/app/application.ml +++ b/app/application.ml @@ -372,7 +372,7 @@ let select_destination state destination = ;; let feed_day_limit = 7 -let sync_error_card_lifetime = Core.Time_ns.Span.of_sec 5. +let sync_error_card_lifetime = 5. let initial_state = { favorites = Journal_routes.Favorites.create ~graph_generation:(-1) @@ -5284,9 +5284,9 @@ let start let startup_loading_key state = Journal_startup.Presentation.loading_request state.startup_presentation in let prev_startup_loading_key = ref None in let arm_startup_loading_timer key = - let started = Core.Time_ns.now () in + let started = Mtime_clock.counter () in schedule_after 0.1 (fun () -> Effect.run (set_state (fun state -> - let elapsed = Core.Time_ns.(Span.to_sec (diff (now ()) started)) in + let elapsed = Mtime.Span.to_float_ns (Mtime_clock.count started) *. 1e-9 in let next = Journal_startup.Presentation.step state.startup_presentation (Elapsed(key,elapsed)) in if next == state.startup_presentation then state else {state with startup_presentation=next}))) in @@ -5295,12 +5295,12 @@ let start in let prev_detail_loading_key = ref (detail_loading_key initial_state) in let arm_detail_loading_timer graph_generation entry_id request_generation = - let started = Core.Time_ns.now () in + let started = Mtime_clock.counter () in schedule_after 0.1 (fun () -> Effect.run (set_state (fun state -> if state.graph_state.generation <> graph_generation then state else - let elapsed = Core.Time_ns.(Span.to_sec (diff (now ()) started)) in + let elapsed = Mtime.Span.to_float_ns (Mtime_clock.count started) *. 1e-9 in let routes = Journal_routes.observe_loading_delay state.routes ~entry_id ~request_generation ~elapsed in if routes == state.routes then state else { state with routes }))) @@ -5309,7 +5309,7 @@ let start let arm_sync_error_timer sequence = incr sync_error_timer_generation; let generation = !sync_error_timer_generation in - schedule_after (Core.Time_ns.Span.to_sec sync_error_card_lifetime) (fun () -> + schedule_after sync_error_card_lifetime (fun () -> if !sync_error_timer_generation = generation then send_action diff --git a/app/dune b/app/dune index a7207fc..7c802a6 100644 --- a/app/dune +++ b/app/dune @@ -39,8 +39,7 @@ journal_symbols) (libraries rrbvec - base - core + mtime.clock mldoc lui ocaml-signal diff --git a/docs/agent-guide/implemented/simplification/2026-10-17-mtime-without-core.md b/docs/agent-guide/implemented/simplification/2026-10-17-mtime-without-core.md new file mode 100644 index 0000000..3a54e3f --- /dev/null +++ b/docs/agent-guide/implemented/simplification/2026-10-17-mtime-without-core.md @@ -0,0 +1,117 @@ +# Mtime Without Core + +## Problem + +Journal uses Jane Street Core only to measure two loading delays and express a five-second notification lifetime. The application needs monotonic elapsed time for the loading gates; calendar clock adjustments must not affect them. Core also remains a declared dependency and appears in two package locks. + +## Proposal + +Replace the two application elapsed-time measurements with `Mtime_clock.counter` / `Mtime_clock.count`, converting `Mtime.span` nanoseconds to floating-point seconds with `Mtime.Span.to_float_ns span *. 1e-9`. Keep the notification lifetime as `5.` seconds and keep the existing `Thread.create`, `Unix.sleepf`, pump delivery, running flag and generation checks. Do not use monotonic values as calendar timestamps. + +The initially approved protected-file patch was extended by the user’s explicit Base-cleanup authorization. Its final scope is: + +- `app/dune`: replace library `core` with `mtime.clock` and remove unused direct library `base`. +- `dune-project`: in the `logseq_journal` package, replace `(core (= v0.17.2))` with `(mtime (= 2.1.0))` and remove unused `(base (= v0.17.3))`. +- `logseq_journal.opam`: replace `"core" {= "v0.17.2"}` with `"mtime" {= "2.1.0"}` and remove unused `"base" {= "v0.17.3"}`. +- `logseq_journal.opam.locked` and `logseq_db_worker.opam.locked`: remove Core and 52 constraints belonging exclusively to its dependency closure, including Base, Stdio and unused Core PPX packages. The exact removed-name set and per-edge dependency evidence live in the task’s external `evidence/exact-dependency-closure.json`. Both already lock Mtime 2.1.0. Preserve all retained versions and every pin; do not prune unrelated stale constraints or compiler `base-*` pseudo-packages. + +No `.mli`, `spec/`, other Dune file or dependency source edit is proposed. Update the existing temporary-notice source boundary assertion and exercise timing ownership through the existing public startup and route reducers. All temporary evidence stays outside the repository. + +Initial investigation used main `fc27cfd62e7fede81185c7ec0bc8807fca797b52`. The parent confirmed PR90, PR91 and PR92 merged at main `87d0cccd0d65e77958a090d4181c7b9c9bd5fb94`. This isolated branch was fast-forwarded to that exact revision. The five protected dependency files have no changes between these two main revisions, and the six Core timing references remain the only application use. The updated journal-build producer-only instructions were read; the approved five-file patch and Base extension were implemented and validated after the resource window was released. + +## Decision + +Use Mtime counters for elapsed loading time and apply the approved five-file dependency patch plus the user-authorized Base cleanup in those same files. Keep all existing timer scheduling and owner fencing. + +## Alternatives considered + +### Keep wall-clock elapsed measurements + +Rejected because adjusting system calendar time can change elapsed loading time. Mtime 2.1.0 is already locked and its public `mtime.clock` library supports counters directly. + +### Rewrite scheduling or introduce a new timer abstraction + +Rejected because this task only changes elapsed-time measurement and dependency identity. The existing public reducers own cancellation and stale-result fencing; changing scheduling would expand the behavioral scope. + +### Remove similarly named packages or shared switch installations + +Rejected. Jane Street Base, compiler `base-*` pseudo-packages and the project-specific `Core` modules, `melange-edn-core` and `melange-transit-core` are separate dependencies. Base itself is now authorized for removal after proving it is unused; retain the unrelated names. The old global switch contains outdated Mldoc metadata and is not evidence of the current pinned dependency graph. Do not modify another owner's switch or pins. + +## Acceptance criteria + +- Receive explicit approval for the exact dependency/Dune/lock patch before applying it; record the response and transition to proposed before changing other repository files. +- Recheck current main and use an isolated branch with no unrelated task changes. Do not push, open a PR, merge or install on an iPhone. +- Verify dependency removal first fails against the baseline and passes after implementation; retain the existing behavioral tests for the 100ms loading boundary, ready/completed/failed/retired owners, retry and graph generations, startup background interruption and fresh resume grace. Add only missing coverage at those public pure-owner boundaries. +- Build all source targets and run the complete test suite with the prepared locked switch after the parent releases the CPU/Simulator window. Follow the current journal-build entry point and provenance checks. +- Build baseline and changed Apps with the same target, configuration, toolchain and signing inputs, record exact hashes and sizes, inspect actual link inputs and Core symbols, and perform Simulator runtime checks without creating devices or changing private graphs. +- Verify the iPhoneOS target compiles/links and preserve any host-restamp ABI limitation. Host restamping is never proof of a complete cross-compiled OCaml ABI. +- Run spec-dev-tool check --all and report remaining limitations honestly, with no predicted 2.09MB saving claim. + +## Risks + +- Mtime 2.1.0 uses `mach_continuous_time` on Darwin, including system sleep. Startup's foreground event retires the previous serial and resume creates a fresh grace period. Detail owns no foreground reset; its existing owner and request generation checks continue to govern a callback delivered after suspension. Preserve these semantics. +- The current global switch's old Mldoc metadata requires Core, Core_bench and Core_unix. The verified task10 prepared switch has pinned Mldoc b3e06c and no installed package depending on Core; use that switch's recorded identity, not the stale global switch, for validation. +- Official opam direct-dependency queries at every exact installed package version show no Core or Base in the Journal or Worker production/build closure. Version-ambiguous recursive queries can traverse older recipes and give misleading Base chains. Current URI/IPaddr/Macaddr references to `ppx_sexp_conv` are upstream `with-test` dependencies; their runtime libraries and Journal’s Yojson PPX driver do not require Base. Remove only Core-exclusive constraints, preserving shared `sexplib0`, `sexplib`, `parsexp` and all other live build dependencies. +- PR92’s maintained producer-only route was used at the final main identity. iOS objects still use the explicit experimental host-restamp importer; record `cross_abi_validated=false` and do not infer a physical-device runtime result. + +## Questions + +- Approved. The parent relayed the human user’s explicit “允许” response to the exact five-file patch on 2026-10-17. No `.mli` or `spec/` edits are included. + +## Authorization + +The approved scope is `app/dune`, `dune-project`, `logseq_journal.opam`, `logseq_journal.opam.locked` and `logseq_db_worker.opam.locked` with only the replacements/deletions listed above. The original task authorizes the matching application implementation and relevant tests. The parent confirmed the Timeline performance experiment released the heavy-build/Simulator window at 09:17:40 UTC on 2026-10-17. Full tests and target builds are now authorized; only device 1446 may be used for isolated synthetic acceptance and its existing app/data must remain untouched. + +## Base cleanup authorization + +The parent relayed the human user’s explicit instruction: “如果能清理掉就清理,检查是不是依赖库依赖了base”. This authorizes removing the unused direct Base declarations in the same three files and handling the same two locks according to the real dependency closure, without upstream edits. No additional protected file is required. A Base-removal boundary test failed on all five existing declarations before removal. + +## Validation progress + +The approved implementation passes startup, route and source-boundary targeted tests, `dune build @all app/native_embed.exe.o` and full `dune runtest --force` with the original prepared switch, Release profile and two jobs. The candidate complete object has zero defined Core/Base symbols and retains Mtime/Mtime_clock. The new clone reuses the original CI pin-resolution record through a read-only ignored pointer; no pins, switch or producer proof was modified. Target App/link, size and bounded Simulator checks are recorded below. + +## Consequences + +### Core-only validation checkpoint + +- Implementation commit `45f845cdd704ead5be09e6b79eca9810363daa50` changes six production/config/dependency files and three existing test files. No `.mli`, `spec/`, upstream source or scheduling change was made. +- Dependency-boundary checks failed before Core/Base removal and passed afterwards. Targeted startup/routes/source-boundary tests, the complete source build and full test suite passed with Release profile and the original prepared switch. The final source verification was run once; subsequent changes are documentation only. +- The native link command now uses 85 `.cmxa` archives instead of 136 and has no Core/Base archive input. Candidate Simulator and iPhoneOS binaries each contain zero Core/Base defined or undefined symbols. Installed Core/Base packages in the shared switch were not uninstalled and are not evidence of final retention. +- Baseline `87d0ccc` and candidate `45f845c` built in the same absolute source path with identical Release, SDK, deployment, compiler, Swift/LUI and signing inputs. Simulator executable bytes changed from 38,023,216 to 29,622,656; App file bytes changed from 39,884,448 to 31,483,888. iPhoneOS executable bytes changed from 38,089,744 to 29,672,768; App file bytes changed from 39,975,900 to 31,558,924. These are actual signed-file sizes, not compressed download sizes or independent Core-versus-Base attribution estimates. +- Both target pairs report `status: built`. Target C/Swift compilation, platform/provider/link-map checks and signatures passed. They remain experimental host-restamp builds with `cross_abi_validated=false`; a validated OCaml iPhoneOS cross toolchain/ABI and physical-device runtime acceptance remain unavailable. Nothing was installed on an iPhone. +- The actual production candidate Simulator App launched to native Logseq sign-in. The independent synthetic warm-start probe did not reach Capture/detail: diagnostics remained Loading catalog / Graph Closed. A control with the same Swift host and initial generated fixture linked to baseline `87d0ccc` reproduces persistent Loading and fetch-catalog start. The root cause is not established; detail and foreground-resume UI acceptance are explicitly incomplete. No product workaround was added, and this task did not expand into fixing that fixture. +- On release, 1446’s original scroll-top bundle was restored and its executable plus all 18 data-file hashes remained unchanged. Two Simulator devices remain; A135 and private graphs were untouched. All task build/test/sampling work stopped before handoff. +- Independent read-only session `01a1493a-75ec-7e93-ad28-1d6045a13b3a` used journal-code-review on `87d0ccc..45f845c` and found no evidence-backed issue. It separately confirmed the UI/ABI limitations and performed no build, test or Simulator operation. +- The task document validates. Full decision-document validation still reports three unchanged historical documents missing required sections; no unrelated documentation repair was made. No push, PR or merge was performed. + +External task evidence includes `completion-report.txt`, `final-artifact-comparison.json`, `target-builds.json`, `targeted-tests.json`, `full-checks.json`, `exact-dependency-closure.json`, `simulator-acceptance.json`, `1446-original-fixture-preserved.json` and `independent-review.txt`. + + +## PR publication scope and evidence + +On 2026-10-17 the user explicitly requested publishing the Core cleanup PR as a regular, non-draft PR. This +supersedes the initial no-push/no-PR restriction for this branch only; no merge or +physical iPhone installation is authorized. The fetched latest main is still +`87d0cccd0d65e77958a090d4181c7b9c9bd5fb94`, so no source rebase or rebuild is needed. +The final PR contains only Core/Mtime and the authorized unused Base cleanup, +three existing test files and this decision document. Every non-Markdown source, +test and dependency input remains identical to verified implementation `45f845c`. + +Core-only full build and forced tests passed: 21 Alcotest suites and 907 cases, +with 115 named running checks reported separately. The Core-only target receipts +and measured sizes above remain applicable; later documentation commits do not +change their native inputs. Detailed records remain in external `full-checks.json`, +`full-checks.log`, `target-builds.json` and `final-artifact-comparison.json`. + +The later local-restoration repair is preserved only on the separate local branch +`codex/fix-local-restore-auth-order-20261017` at `e5b9b2b`; none of its production +changes, Application tests or decision document belongs to this PR. Its 915-case +suite and successful encrypted startup/detail/foreground UI acceptance are not +validation results for this Core-only branch. Core-only production Simulator +sign-in succeeded, but synthetic detail and resume acceptance remains incomplete +as documented at the checkpoint. The initial fixture and baseline restoration +issues were investigated separately; this PR does not repair them. + +Publishing reuses verified evidence without another heavy build or Simulator run, +preserving the current Timeline performance resource window. A fresh independent +journal-code-review session must review the published PR's final head and scope. diff --git a/dune-project b/dune-project index ee12dad..8c0c041 100644 --- a/dune-project +++ b/dune-project @@ -92,8 +92,7 @@ (logseq_sync (= 0.1.0)) (lui (= 0.1.0)) (ocaml-signal (= 0.1.0)) - (base (= v0.17.3)) - (core (= v0.17.2)) + (mtime (= 2.1.0)) (datascript_ocaml (= dev)) (datascript-ocaml-native (= dev)) (melange-edn-core (= 0.5.0)) diff --git a/logseq_db_worker.opam.locked b/logseq_db_worker.opam.locked index 5f27d91..6916923 100644 --- a/logseq_db_worker.opam.locked +++ b/logseq_db_worker.opam.locked @@ -11,7 +11,6 @@ depends: [ "angstrom" {= "dev"} "asn1-combinators" {= "0.3.3"} "astring" {= "0.8.5"} - "base" {= "v0.17.3"} "base-bigarray" {= "base"} "base-bytes" {= "base"} "base-domains" {= "base"} @@ -20,20 +19,15 @@ depends: [ "base-threads" {= "base"} "base-unix" {= "base"} "base64" {= "3.5.2"} - "base_bigstring" {= "v0.17.0"} - "base_quickcheck" {= "v0.17.1"} "bigstringaf" {= "0.10.0"} - "bin_prot" {= "v0.17.0-1"} "bos" {= "0.3.0"} "ca-certs-nss" {= "3.126"} - "capitalization" {= "v0.17.0"} "cmdliner" {= "2.1.1"} "compiler-cloning" {= "disabled"} "conf-gmp" {= "5"} "conf-gmp-powm-sec" {= "4"} "conf-pkg-config" {= "5"} "conf-sqlite3" {= "1"} - "core" {= "v0.17.2"} "cppo" {= "1.8.0"} "csexp" {= "1.5.2"} "cstruct" {= "6.2.0"} @@ -53,10 +47,8 @@ depends: [ "eqaf" {= "0.10"} "ezjsonm" {= "1.3.0"} "faraday" {= "0.8.2"} - "fieldslib" {= "v0.17.0"} "fmt" {= "0.11.0"} "fpath" {= "0.7.3"} - "gel" {= "v0.17.0"} "gen" {= "1.1"} "gluten" {= "0.5.2"} "gluten-eio" {= "0.5.2"} @@ -67,14 +59,11 @@ depends: [ "httpun-eio" {= "0.2.0"} "httpun-types" {= "0.2.0"} "httpun-ws" {= "0.2.0"} - "int_repr" {= "v0.17.0"} "iomux" {= "0.4"} "ipaddr" {= "5.6.2"} - "jane-street-headers" {= "v0.17.0"} "js_of_ocaml" {= "6.4.1"} "js_of_ocaml-compiler" {= "6.4.1"} "jsonm" {= "1.0.2"} - "jst-config" {= "v0.17.0"} "kdf" {= "1.1.1"} "logs" {= "0.10.0"} "logseq_db_storage" {= "0.1.0"} @@ -107,7 +96,6 @@ depends: [ "ocaml-compiler-libs" {= "v0.17.0"} "ocaml-options-vanilla" {= "1"} "ocaml-syntax-shims" {= "1.0.0"} - "ocaml_intrinsics_kernel" {= "v0.17.2"} "ocamlbuild" {= "0.16.1"} "ocamlfind" {= "1.9.9~preview"} "ocplib-endian" {= "1.2"} @@ -115,46 +103,10 @@ depends: [ "optint" {= "0.3.0"} "parsexp" {= "v0.17.0"} "persistent_sorted_set_ocaml" {= "dev"} - "ppx_assert" {= "v0.17.0"} - "ppx_base" {= "v0.17.0"} - "ppx_bench" {= "v0.17.1"} - "ppx_bin_prot" {= "v0.17.1"} - "ppx_cold" {= "v0.17.0"} - "ppx_compare" {= "v0.17.0"} - "ppx_custom_printf" {= "v0.17.0"} "ppx_derivers" {= "1.2.1"} "ppx_deriving" {= "6.2.0"} "ppx_deriving_yojson" {= "3.10.0"} - "ppx_diff" {= "v0.17.1"} - "ppx_disable_unused_warnings" {= "v0.17.0"} - "ppx_enumerate" {= "v0.17.0"} - "ppx_expect" {= "v0.17.3"} - "ppx_fields_conv" {= "v0.17.0"} - "ppx_fixed_literal" {= "v0.17.0"} - "ppx_globalize" {= "v0.17.2"} - "ppx_hash" {= "v0.17.0"} - "ppx_here" {= "v0.17.0"} - "ppx_ignore_instrumentation" {= "v0.17.0"} - "ppx_inline_test" {= "v0.17.1"} - "ppx_jane" {= "v0.17.0"} - "ppx_let" {= "v0.17.1"} - "ppx_log" {= "v0.17.0"} - "ppx_module_timer" {= "v0.17.0"} - "ppx_optcomp" {= "v0.17.1"} - "ppx_optional" {= "v0.17.0"} - "ppx_pipebang" {= "v0.17.0"} - "ppx_sexp_conv" {= "v0.17.1"} - "ppx_sexp_message" {= "v0.17.0"} - "ppx_sexp_value" {= "v0.17.0"} - "ppx_stable" {= "v0.17.1"} - "ppx_stable_witness" {= "v0.17.0"} - "ppx_string" {= "v0.17.0"} - "ppx_string_conv" {= "v0.17.0"} - "ppx_tydi" {= "v0.17.1"} - "ppx_typerep_conv" {= "v0.17.1"} - "ppx_variants_conv" {= "v0.17.1"} "ppxlib" {= "0.38.0"} - "ppxlib_jane" {= "v0.17.4"} "psq" {= "0.2.1"} "ptime" {= "1.2.0"} "rrbvec" {= "dev"} @@ -163,22 +115,17 @@ depends: [ "seq" {= "base"} "sexplib" {= "v0.17.0"} "sexplib0" {= "v0.17.0"} - "splittable_random" {= "v0.17.0"} "sqlite3" {= "5.4.0"} - "stdio" {= "v0.17.0"} "stdlib-shims" {= "0.3.0"} "stringext" {= "1.6.0"} "thread-table" {= "1.0.0"} - "time_now" {= "v0.17.0"} "tls" {= "2.1.2"} "tls-eio" {= "2.1.2"} "topkg" {= "1.1.1"} - "typerep" {= "v0.17.1"} "uri" {= "4.4.0"} "uucp" {= "17.0.0"} "uunf" {= "17.0.0"} "uutf" {= "1.0.4"} - "variantslib" {= "v0.17.0"} "x509" {= "1.1.1"} "yojson" {= "3.0.0"} "zarith" {= "1.14"} diff --git a/logseq_journal.opam b/logseq_journal.opam index 5885053..23fb6c6 100644 --- a/logseq_journal.opam +++ b/logseq_journal.opam @@ -17,9 +17,8 @@ depends: [ "logseq_sync" {= "0.1.0"} "lui" {= "0.1.0"} "ocaml-signal" {= "0.1.0"} - "base" {= "v0.17.3"} "bigstringaf" {= "0.10.0"} - "core" {= "v0.17.2"} + "mtime" {= "2.1.0"} "mldoc" {= "dev"} "ca-certs-nss" {= "3.126"} "cstruct" {= "6.2.0"} diff --git a/logseq_journal.opam.locked b/logseq_journal.opam.locked index 725e7bd..fdeff38 100644 --- a/logseq_journal.opam.locked +++ b/logseq_journal.opam.locked @@ -59,7 +59,6 @@ depends: [ "angstrom" {= "dev"} "asn1-combinators" {= "0.3.3"} "astring" {= "0.8.5"} - "base" {= "v0.17.3"} "base-bigarray" {= "base"} "base-bytes" {= "base"} "base-domains" {= "base"} @@ -68,20 +67,15 @@ depends: [ "base-threads" {= "base"} "base-unix" {= "base"} "base64" {= "3.5.2"} - "base_bigstring" {= "v0.17.0"} - "base_quickcheck" {= "v0.17.1"} "bigstringaf" {= "0.10.0"} - "bin_prot" {= "v0.17.0-1"} "bos" {= "0.3.0"} "ca-certs-nss" {= "3.126"} - "capitalization" {= "v0.17.0"} "cmdliner" {= "2.1.1"} "compiler-cloning" {= "disabled"} "conf-gmp" {= "5"} "conf-gmp-powm-sec" {= "4"} "conf-pkg-config" {= "5"} "conf-sqlite3" {= "1"} - "core" {= "v0.17.2"} "cppo" {= "1.8.0"} "csexp" {= "1.5.2"} "cstruct" {= "6.2.0"} @@ -101,11 +95,9 @@ depends: [ "eqaf" {= "0.10"} "ezjsonm" {= "1.3.0"} "faraday" {= "0.8.2"} - "fieldslib" {= "v0.17.0"} "fix" {= "20250919"} "fmt" {= "0.11.0"} "fpath" {= "0.7.3"} - "gel" {= "v0.17.0"} "gen" {= "1.1"} "gluten" {= "0.5.2"} "gluten-eio" {= "0.5.2"} @@ -116,14 +108,11 @@ depends: [ "httpun-eio" {= "0.2.0"} "httpun-types" {= "0.2.0"} "httpun-ws" {= "0.2.0"} - "int_repr" {= "v0.17.0"} "iomux" {= "0.4"} "ipaddr" {= "5.6.2"} - "jane-street-headers" {= "v0.17.0"} "js_of_ocaml" {= "6.4.1"} "js_of_ocaml-compiler" {= "6.4.1"} "jsonm" {= "1.0.2"} - "jst-config" {= "v0.17.0"} "kdf" {= "1.1.1"} "logs" {= "0.10.0"} "logseq_db_storage" {= "0.1.0"} @@ -162,7 +151,6 @@ depends: [ "ocaml-options-vanilla" {= "1"} "ocaml-signal" {= "0.1.0"} "ocaml-syntax-shims" {= "1.0.0"} - "ocaml_intrinsics_kernel" {= "v0.17.2"} "ocamlbuild" {= "0.16.1"} "ocamlfind" {= "1.9.9~preview"} "ocplib-endian" {= "1.2"} @@ -170,46 +158,10 @@ depends: [ "optint" {= "0.3.0"} "parsexp" {= "v0.17.0"} "persistent_sorted_set_ocaml" {= "dev"} - "ppx_assert" {= "v0.17.0"} - "ppx_base" {= "v0.17.0"} - "ppx_bench" {= "v0.17.1"} - "ppx_bin_prot" {= "v0.17.1"} - "ppx_cold" {= "v0.17.0"} - "ppx_compare" {= "v0.17.0"} - "ppx_custom_printf" {= "v0.17.0"} "ppx_derivers" {= "1.2.1"} "ppx_deriving" {= "6.2.0"} "ppx_deriving_yojson" {= "3.10.0"} - "ppx_diff" {= "v0.17.1"} - "ppx_disable_unused_warnings" {= "v0.17.0"} - "ppx_enumerate" {= "v0.17.0"} - "ppx_expect" {= "v0.17.3"} - "ppx_fields_conv" {= "v0.17.0"} - "ppx_fixed_literal" {= "v0.17.0"} - "ppx_globalize" {= "v0.17.2"} - "ppx_hash" {= "v0.17.0"} - "ppx_here" {= "v0.17.0"} - "ppx_ignore_instrumentation" {= "v0.17.0"} - "ppx_inline_test" {= "v0.17.1"} - "ppx_jane" {= "v0.17.0"} - "ppx_let" {= "v0.17.1"} - "ppx_log" {= "v0.17.0"} - "ppx_module_timer" {= "v0.17.0"} - "ppx_optcomp" {= "v0.17.1"} - "ppx_optional" {= "v0.17.0"} - "ppx_pipebang" {= "v0.17.0"} - "ppx_sexp_conv" {= "v0.17.1"} - "ppx_sexp_message" {= "v0.17.0"} - "ppx_sexp_value" {= "v0.17.0"} - "ppx_stable" {= "v0.17.1"} - "ppx_stable_witness" {= "v0.17.0"} - "ppx_string" {= "v0.17.0"} - "ppx_string_conv" {= "v0.17.0"} - "ppx_tydi" {= "v0.17.1"} - "ppx_typerep_conv" {= "v0.17.1"} - "ppx_variants_conv" {= "v0.17.1"} "ppxlib" {= "0.38.0"} - "ppxlib_jane" {= "v0.17.4"} "psq" {= "0.2.1"} "ptime" {= "1.2.0"} "reason" {= "3.18.0"} @@ -219,22 +171,17 @@ depends: [ "seq" {= "base"} "sexplib" {= "v0.17.0"} "sexplib0" {= "v0.17.0"} - "splittable_random" {= "v0.17.0"} "sqlite3" {= "5.4.0"} - "stdio" {= "v0.17.0"} "stdlib-shims" {= "0.3.0"} "stringext" {= "1.6.0"} "thread-table" {= "1.0.0"} - "time_now" {= "v0.17.0"} "tls" {= "2.1.2"} "tls-eio" {= "2.1.2"} "topkg" {= "1.1.1"} - "typerep" {= "v0.17.1"} "uri" {= "4.4.0"} "uucp" {= "17.0.0"} "uunf" {= "17.0.0"} "uutf" {= "1.0.4"} - "variantslib" {= "v0.17.0"} "x509" {= "1.1.1"} "yojson" {= "3.0.0"} "zarith" {= "1.14"} diff --git a/test/journal_routes_test.ml b/test/journal_routes_test.ml index 7354217..be188f5 100644 --- a/test/journal_routes_test.ml +++ b/test/journal_routes_test.ml @@ -3175,9 +3175,12 @@ let test_detail_initial_loading_delay_and_ownership () = let id = entry_id t in require (not (R.loading_indicator t)) "slow route starts with a spinner"; require (R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:(-1.) == t) "negative elapsed time changes owner"; + require (R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:nan == t) "NaN elapsed time changes owner"; require (R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:0.099 == t) "early callback changes owner"; + require (R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:0.099999999 == t) "one nanosecond before 100ms shows loading"; let slow = R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:0.1 in require (R.loading_indicator slow) "100ms pending route has no indicator"; + require (R.loading_indicator (R.observe_loading_delay t ~entry_id:id ~request_generation:9001L ~elapsed:3600.)) "suspended pending route loses its elapsed loading delay"; require (R.detail slow = None) "pending route exposes a partial root"; require (R.observe_loading_delay slow ~entry_id:id ~request_generation:9001L ~elapsed:0.2 == slow) "duplicate delay republishes owner"); "failure and retry", (fun () -> diff --git a/test/source_boundary_test.ml b/test/source_boundary_test.ml index bad6a45..b1ac254 100644 --- a/test/source_boundary_test.ml +++ b/test/source_boundary_test.ml @@ -158,14 +158,26 @@ let test_sync_error_card_is_temporary_and_error_only root = (fun required -> if not (contains application required) then fail "sync-error timeout behavior is missing %S" required) - [ "let sync_error_card_lifetime = Core.Time_ns.Span.of_sec 5." + [ "let sync_error_card_lifetime = 5." ; "let arm_sync_error_timer sequence =" ; "let sync_error_timer_generation = ref 0 in" - ; "schedule_after (Core.Time_ns.Span.to_sec sync_error_card_lifetime)" + ; "schedule_after sync_error_card_lifetime" ; "!sync_error_timer_generation = generation" ] ;; +let test_no_jane_street_core_or_base_dependency root = + forbid_text root "app/application.ml" [ "Core.Time_ns" ]; + forbid_text root "app/dune" [ "\n core\n"; "\n base\n" ]; + require_text root "app/dune" [ "\n mtime.clock\n" ]; + forbid_text root "dune-project" [ "(core ("; "(base (" ]; + require_text root "dune-project" [ "(mtime (= 2.1.0))" ]; + List.iter (fun relative -> forbid_text root relative [ "\"core\" {"; "\"base\" {" ]) + [ "logseq_journal.opam"; "logseq_journal.opam.locked" + ; "logseq_db_worker.opam.locked" ]; + require_text root "logseq_journal.opam" [ "\"mtime\" {= \"2.1.0\"}" ] +;; + let contains_dune_internal_module_path contents = let is_identifier_character = function | 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' -> true @@ -1120,6 +1132,7 @@ let () = test_repository_local_runtime_tests root; test_sync_transport_is_websocket_only root; test_sync_error_card_is_temporary_and_error_only root; + test_no_jane_street_core_or_base_dependency root; require_exact_dependency root "logseq_journal.opam" ~package:"lui" ~version:"0.1.0"; require_exact_dependency root diff --git a/test/startup_test.ml b/test/startup_test.ml index 95b8da0..a093c1d 100644 --- a/test/startup_test.ml +++ b/test/startup_test.ml @@ -254,6 +254,8 @@ let test_stable_startup_presentation () = let key=timer t in let early=P.step t (Elapsed(key,0.099)) in require (not(P.loading_indicator early)) "99ms shows loading"; + require (P.step early (Elapsed(key,0.099999999))==early) + "one nanosecond before 100ms shows loading"; let t=observe ~manager:(startup_snapshot ~restoring_local:true ()) early in require (timer t=key) "busy phase restarts grace"; let slow=P.step t (Elapsed(key,0.1)) in @@ -325,7 +327,12 @@ let test_stable_startup_presentation () = "background keeps an active loading timer"; let resumed=P.step inactive (Foreground true) in require (timer resumed<>old && not(P.loading_indicator resumed)) "resume reuses old grace"; - require (P.step resumed (Elapsed(old,1.))==resumed) "late background timer changes resume"); + require (P.step resumed (Elapsed(old,3600.))==resumed) "late background timer changes resume"; + let key=timer resumed in + require (P.step resumed (Elapsed(key,0.099999999))==resumed) + "resume counts suspended time towards its fresh grace"; + require (P.loading_indicator (P.step resumed (Elapsed(key,0.1)))) + "resume does not show loading after its fresh 100ms grace"); "negative/NaN elapsed and explicit signout are safe",(fun () -> let t=observe ~manager:(startup_snapshot ~restoring_local:true ()) (P.create ()) in let key=timer t in