{"owner":"logseq","repo":"mobile","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":3205,"categories":["root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".agents/skills/testing-ios-simulator/SKILL.md",".agents/skills/testing-ocaml-core-linux/SKILL.md"],"skills":{"AGENTS.md":"# Logseq\n\nLogseq uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`.\n\n## Testing\n\n- Do NOT run `swift test` (xctest). It hangs indefinitely in this\n  environment (an async Swift Testing case blocks on an XCTWaiter that never\n  finishes), wasting many minutes per run. Do not run it.\n- Validate OCaml core changes with `dune build @shared/native/runtest`.\n- If a Swift compile check is needed, use `swift build --package-path apple` (build only, no test\n  run) with sandbox disabled; SwiftPM's own sandbox conflicts with the agent\n  sandbox.\n\n## Build system\n\n- Use `dune build @shared/native/runtest` for core validation. The mobile entry object\n  also needs platform libraries and FFI symbols supplied by the mobile build.\n  Crypto protocol handling lives in `shared/src/logseq/core/platform_crypto.ml`.\n  The mobile-only `logseq_crypto_call` FFI declaration lives in\n  `shared/src/logseq/native_crypto.ml` so CLI builds do not require mobile symbols.\n- Mobile OCaml builds use the thin `scripts/build-mobile-ocaml.sh` Dune wrapper.\n  Native module membership lives in `shared/native/dune_modules/*.sexp`. Core sources\n  live in `shared/src/logseq/core`; adding one needs no per-file rule.\n\n## Cursor Cloud specific instructions\n\nCloud Agent VMs are Linux. They cannot run Xcode, the iOS simulator, or `swift test`. Do not try to start those from this environment.\n\nThe Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app's default API is `https://api.logseq.io`. Local sync testing can explicitly override it with `http://127.0.0.1:8787` from the separate Logseq server repository.\n\n### OCaml core\n\nUse the `5.5.0` opam switch (create it if needed with `opam switch create 5.5.0`):\n\n```sh\neval $(opam env --switch=5.5.0)\ndune runtest\n```\n\n`dune runtest` is the lint/test/build gate here. `dune build` of `logseq_mobile_entry` looks for SQLite via a Homebrew path in `shared/native/dune`; on Linux, either skip that executable or set `LIBRARY_PATH` to your system SQLite lib dir (e.g. `/usr/lib/x86_64-linux-gnu` on Debian/Ubuntu) first.\n\n`opam install . --deps-only` does not apply nested pins from `datascript-ocaml-native`. Pin these first (idempotent):\n\n```sh\nopam pin add -n -y melange-edn-core git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-edn-native git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-transit-core git+https://github.com/logseq/melange-transit.git#main\nopam pin add -n -y melange-transit-native git+https://github.com/logseq/melange-transit.git#main\nopam install . --deps-only --yes --with-test\n```\n\n`opam init` on this VM must use `--disable-sandboxing`. New shells need `eval $(opam env --switch=5.5.0)` unless `.bashrc` already loads it.\n\nA representative core action is the Swift FFI RPC `dispatch` / `send`, which optimistic-captures a journal block (see `shared/test/logseq/rpc_test.ml` and `dune build @shared/native/runtest`).\n\n- Avoid O(n²) `List` patterns such as `List.concat` and repeated `List.append` on large sequences; when the project already depends on the `rrbvec` package, use `Rrbvec` vectors instead.\n\n### iOS / Android\n\nOn a Mac, follow `README.md`: open `apple/Project.xcworkspace`, run the `Logseq App` scheme. Native core builds (`scripts/build-mobile-ios-*.sh`, `scripts/build-android-native.sh`) bootstrap their own cross toolchains under `_build/` via the `scripts/bootstrap-*.sh` helpers. Do not start Android emulators or Maestro from Cloud Agent unless that stack is explicitly in scope.\n",".agents/skills/testing-ios-simulator/SKILL.md":"---\nname: testing-ios-simulator\ndescription: Build and launch the Logseq iOS app in an iOS simulator on macOS arm64 (Xcode + cross OCaml toolchain), including the iOS SDK function-detection pitfalls in bootstrap-ios-ocaml.sh.\n---\n\n# Logseq iOS Simulator Build & Launch\n\n## Prerequisites\n- macOS arm64 with Xcode installed (`xcodebuild -version` works).\n- opam switch `5.5.0` with dune (`opam exec --switch=5.5.0 -- dune --version`).\n- An iOS simulator: `xcrun simctl list devices available | grep iPhone`; boot one with\n  `xcrun simctl boot <UDID>`.\n\n## Build steps\n1. `scripts/bootstrap-ios-ocaml.sh simulator` — builds host + cross OCaml 5.5.0 under\n   `_build/apple-toolchains/ios/` (long first run; stamps skip rebuilds).\n2. `scripts/build-mobile-ios-simulator.sh` — builds `shared/native/logseq_mobile_entry.exe.o`\n   via dune context `ios_simulator`, then `swift build` (product `LogseqShell`),\n   xcodebuild for the share/widget extensions, and assembles+codesigns\n   `.build/Logseq.app`. Note: the script can exit non-zero at the end even when all\n   artifacts are produced correctly — re-running it (incremental) and checking for\n   `.build/Logseq.app/Logseq` is the practical check.\n3. `xcrun simctl install booted .build/Logseq.app`\n4. `xcrun simctl launch booted com.logseq.logseq` → prints `com.logseq.logseq: <pid>`;\n   verify the process stays alive via\n   `xcrun simctl spawn booted launchctl list | grep logseq`.\n5. Screenshot: `xcrun simctl io booted screenshot out.png`.\n\n## Pitfalls\n- `bootstrap-ios-ocaml.sh` host `./configure` must pass `--without-zstd`, else\n  zstd-compressed .cmi files break the LG toolchain later (LG2000 errors).\n- Cross-compiling OCaml for iOS: configure's link-only `AC_CHECK_FUNC` detects symbols\n  (pipe2, dup3, accept4, execvpe, prctl, secure_getenv, __secure_getenv) that link but\n  are NOT declared in the iOS SDK headers → \"call to undeclared function\" errors under\n  modern clang. Fix by passing `ac_cv_func_<name>=no` to the target configure. Check for\n  more with a compile probe:\n  `xcrun --sdk iphonesimulator clang -target arm64-apple-ios17.0-simulator -isysroot <sdk> -c t.c`\n  where t.c calls the function after including the SDK headers.\n- First launch may show a local-network permission alert; dismiss it via Simulator UI.\n- The app opens to a \"Logseq / Sign in\" screen (Cognito hosted UI); going past it\n  requires credentials.\n- `duniverse/` pulls only the lockfile dirs (129). The `logseq/*` pins NOT vendored\n  (`datascript-ocaml`, `lg`, `lui`, `mldoc`, `persistent-sorted-set-ocaml`,\n  `signal-lg`) must be cloned manually into `duniverse/` at the SHAs listed in\n  `logseq.opam` — same loop as `.github/workflows/e2e.yml`. A fresh\n  `opam-monorepo pull` wipes these dirs, so re-clone them after each pull.\n- `scripts/build-mobile-ocaml.sh` regenerates `_build/dune-workspace.mobile` from\n  `dune-workspace.mobile`; set `LOGSEQ_OPAM_SWITCH=5.5.0` when running outside\n  `opam exec`.\n\n## Sheet interaction checks\n\n- Follow the existing journal calendar sheet for compact utility presentations. Result-view filter and sort sheets should open partially, with expansion available for longer lists (`medium,large` in the LUI wire format), and retain native navigation actions and swipe dismissal.\n- The custom Logseq palette must reach the complete modal surface, including navigation, list background, and grouped rows. LUI sheets render outside the scoped node tree; propagate the ancestor-resolved semantic colors into their content. Avoid unconditional system grouped backgrounds when a theme supplies a background.\n- Use a simulator runtime check to inspect the actual presented frame and screenshot colors in both appearances. For dark Logseq settings, the surrounding sheet background should match the graph background token (`#002D38`), with themed elevated rows. Also exercise Cancel, Done, and scrolling without changing filter/sort semantics.\n- Use `apple/Tests/UI/run-simulator-runtime-check.py` for native checks; do not run `swift test` in this repository.\n\n## Maestro e2e (test-ios-e2e-suite.sh)\n- Install Maestro: `curl -fsSL https://get.maestro.mobile.dev | bash` → `~/.maestro/bin`.\n- The e2e flows hit the app's sync server at `http://127.0.0.1:8787`. That server is\n  `deps/db-sync` in the `logseq` repo, and it MUST run from the\n  `feature/native-mobile-app` branch (the canonical `../logseq-1` checkout) — the app\n  requires `schema-version` in the `/sync/<id>/snapshot/download` response, which only\n  exists there (`main` returns without it → \"Add sync graph\" fails with\n  `NSURLErrorDomain Code=-1017`). Setup:\n  `cd ../logseq-1/deps/db-sync && pnpm install && clojure -M:cljs release db-sync-node`\n  (needs `JAVA_HOME=$(/usr/libexec/java_home -v 21)`), then\n  `DB_SYNC_PORT=8787 DB_SYNC_DATA_DIR=~/db-sync-data ./start.sh`;\n  health check `curl http://127.0.0.1:8787/health`.\n- Run: `LOGSEQ_IOS_SKIP_BUILD=1 LOGSEQ_E2E_USERNAME=<u> LOGSEQ_E2E_PASSWORD=<p> ./scripts/test-ios-e2e-suite.sh smoke`\n  (4 flows: capture-responsive, cold-start-composer, search-status-regression, sidebar).\n- `scripts/test-ios-e2e.sh` wipes the app data container between flows; `<container>/tmp`\n  must be recreated (the script does `mkdir -p`) or the OCaml core crashes writing the\n  initial graph snapshot via `Filename.temp_file` (`Sys_error ...tmp/logseq-initial-*.snapshot`).\n\n## Devin Secrets Needed\n- `LOGSEQ_TEST_USERNAME` / `LOGSEQ_TEST_PASSWORD` for hosted sign-in and e2e.\n",".agents/skills/testing-ocaml-core-linux/SKILL.md":"---\nname: testing-ocaml-core-linux\ndescription: Build and run the OCaml core test gate on Linux (opam deps, duniverse restore, lg prefix cache + dune shared cache, parallel test-chunk layout in shared/test/dune).\n---\n\n# Logseq OCaml core testing on Linux\n\nThe only Linux-runnable surface is the OCaml core in `shared/`. The gate is:\n\n```sh\neval $(opam env)          # 'default' switch here; README documents 5.5.0\ndune build @shared/native/runtest\n```\n\nNever `swift test` — it hangs on Linux.\n\n## Cold-build performance knobs\n\nTwo layered caches make `rm -rf _build` rebuilds fast; keep both warm:\n\n- `Logseq/.lg-cache/` — lg's content-addressed compile cache, outside `_build`,\n  survives clean builds. Prefix keys are recorded in each `*.state` artifact\n  (provenance key, lg >= the cache-fix revision pinned in `logseq.opam`);\n  do not digest state bytes.\n- Dune shared cache — off by default. Enable per machine in\n  `~/.config/dune/config`:\n\n  ```\n  (lang dune 3.0)\n  (cache enabled)\n  ```\n\n  Restores all builtin-rule artifacts (vendored deps, generated-module cmx)\n  on a cold `_build`. The `@runtest` action itself replays from cache when\n  inputs are unchanged.\n\nExpected on an 8-core box: ~40s cold without dune cache, ~13s with it\n(11.6s is the test run — a user rule, only skipped when fully replayed).\nA cold build where `.lg-cache` is ALSO empty recompiles every cljc (~4min).\n\n## Test target layout (shared/test/dune)\n\n- `lg-native-cmi-deps` alias (also in `shared/native/dune`) forces vendored\n  duniverse cmis to exist before lg runs; without it lg falls back to\n  same-named opam cmis and fails with \"inconsistent assumptions\".\n- `logseq_lui_test_base` — chunk compiled off\n  `../native/logseq_lg_core_native.state` (emitted by the core rule's\n  `--emit-state`), emits `include Logseq_lg_core_native` + literal/lui/\n  app/lg-test framework.\n- `logseq_lui_test_p1..p8` — 41 test namespaces as independent chunks\n  off `logseq_lui_test_base.state` (`--compile-files-chunk-from` +\n  `--prefix-interface` pointing at the base cmi). Add new test files to a\n  chunk (or a new chunk) — they compile in parallel.\n- Generated chunk modules must be listed on a LIBRARY (`logseq_lui_test_parts`,\n  `wrapped false`): dune does not emit compile rules for generated modules on\n  an executable. The runner exe needs `(link_flags -linkall)` — test\n  registration is initializer side-effects that dead-stripping drops.\n- `logseq_lui_test_z` is the last module alphabetically: it carries\n  `run.cljc`, which must run after all chunk registrations.\n\n## Environment restore (if duniverse/ is missing)\n\n`duniverse/` is gitignored. Restore per `logseq.opam.locked`: clone the\nopam source trees for each vendored package at the locked commit (private\nrepos lg/lui/signal-lg need `LOGSEQ_GITHUB_PAT`). `duniverse/lg` must match the\nlg pin in `logseq.opam` — `%{bin:lg}` resolves to the vendored copy.\n"},"files":{"AGENTS.md":"# Logseq\n\nLogseq uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`.\n\n## Testing\n\n- Do NOT run `swift test` (xctest). It hangs indefinitely in this\n  environment (an async Swift Testing case blocks on an XCTWaiter that never\n  finishes), wasting many minutes per run. Do not run it.\n- Validate OCaml core changes with `dune build @shared/native/runtest`.\n- If a Swift compile check is needed, use `swift build --package-path apple` (build only, no test\n  run) with sandbox disabled; SwiftPM's own sandbox conflicts with the agent\n  sandbox.\n\n## Build system\n\n- Use `dune build @shared/native/runtest` for core validation. The mobile entry object\n  also needs platform libraries and FFI symbols supplied by the mobile build.\n  Crypto protocol handling lives in `shared/src/logseq/core/platform_crypto.ml`.\n  The mobile-only `logseq_crypto_call` FFI declaration lives in\n  `shared/src/logseq/native_crypto.ml` so CLI builds do not require mobile symbols.\n- Mobile OCaml builds use the thin `scripts/build-mobile-ocaml.sh` Dune wrapper.\n  Native module membership lives in `shared/native/dune_modules/*.sexp`. Core sources\n  live in `shared/src/logseq/core`; adding one needs no per-file rule.\n\n## Cursor Cloud specific instructions\n\nCloud Agent VMs are Linux. They cannot run Xcode, the iOS simulator, or `swift test`. Do not try to start those from this environment.\n\nThe Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app's default API is `https://api.logseq.io`. Local sync testing can explicitly override it with `http://127.0.0.1:8787` from the separate Logseq server repository.\n\n### OCaml core\n\nUse the `5.5.0` opam switch (create it if needed with `opam switch create 5.5.0`):\n\n```sh\neval $(opam env --switch=5.5.0)\ndune runtest\n```\n\n`dune runtest` is the lint/test/build gate here. `dune build` of `logseq_mobile_entry` looks for SQLite via a Homebrew path in `shared/native/dune`; on Linux, either skip that executable or set `LIBRARY_PATH` to your system SQLite lib dir (e.g. `/usr/lib/x86_64-linux-gnu` on Debian/Ubuntu) first.\n\n`opam install . --deps-only` does not apply nested pins from `datascript-ocaml-native`. Pin these first (idempotent):\n\n```sh\nopam pin add -n -y melange-edn-core git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-edn-native git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-transit-core git+https://github.com/logseq/melange-transit.git#main\nopam pin add -n -y melange-transit-native git+https://github.com/logseq/melange-transit.git#main\nopam install . --deps-only --yes --with-test\n```\n\n`opam init` on this VM must use `--disable-sandboxing`. New shells need `eval $(opam env --switch=5.5.0)` unless `.bashrc` already loads it.\n\nA representative core action is the Swift FFI RPC `dispatch` / `send`, which optimistic-captures a journal block (see `shared/test/logseq/rpc_test.ml` and `dune build @shared/native/runtest`).\n\n- Avoid O(n²) `List` patterns such as `List.concat` and repeated `List.append` on large sequences; when the project already depends on the `rrbvec` package, use `Rrbvec` vectors instead.\n\n### iOS / Android\n\nOn a Mac, follow `README.md`: open `apple/Project.xcworkspace`, run the `Logseq App` scheme. Native core builds (`scripts/build-mobile-ios-*.sh`, `scripts/build-android-native.sh`) bootstrap their own cross toolchains under `_build/` via the `scripts/bootstrap-*.sh` helpers. Do not start Android emulators or Maestro from Cloud Agent unless that stack is explicitly in scope.\n",".agents/skills/testing-ios-simulator/SKILL.md":"---\nname: testing-ios-simulator\ndescription: Build and launch the Logseq iOS app in an iOS simulator on macOS arm64 (Xcode + cross OCaml toolchain), including the iOS SDK function-detection pitfalls in bootstrap-ios-ocaml.sh.\n---\n\n# Logseq iOS Simulator Build & Launch\n\n## Prerequisites\n- macOS arm64 with Xcode installed (`xcodebuild -version` works).\n- opam switch `5.5.0` with dune (`opam exec --switch=5.5.0 -- dune --version`).\n- An iOS simulator: `xcrun simctl list devices available | grep iPhone`; boot one with\n  `xcrun simctl boot <UDID>`.\n\n## Build steps\n1. `scripts/bootstrap-ios-ocaml.sh simulator` — builds host + cross OCaml 5.5.0 under\n   `_build/apple-toolchains/ios/` (long first run; stamps skip rebuilds).\n2. `scripts/build-mobile-ios-simulator.sh` — builds `shared/native/logseq_mobile_entry.exe.o`\n   via dune context `ios_simulator`, then `swift build` (product `LogseqShell`),\n   xcodebuild for the share/widget extensions, and assembles+codesigns\n   `.build/Logseq.app`. Note: the script can exit non-zero at the end even when all\n   artifacts are produced correctly — re-running it (incremental) and checking for\n   `.build/Logseq.app/Logseq` is the practical check.\n3. `xcrun simctl install booted .build/Logseq.app`\n4. `xcrun simctl launch booted com.logseq.logseq` → prints `com.logseq.logseq: <pid>`;\n   verify the process stays alive via\n   `xcrun simctl spawn booted launchctl list | grep logseq`.\n5. Screenshot: `xcrun simctl io booted screenshot out.png`.\n\n## Pitfalls\n- `bootstrap-ios-ocaml.sh` host `./configure` must pass `--without-zstd`, else\n  zstd-compressed .cmi files break the LG toolchain later (LG2000 errors).\n- Cross-compiling OCaml for iOS: configure's link-only `AC_CHECK_FUNC` detects symbols\n  (pipe2, dup3, accept4, execvpe, prctl, secure_getenv, __secure_getenv) that link but\n  are NOT declared in the iOS SDK headers → \"call to undeclared function\" errors under\n  modern clang. Fix by passing `ac_cv_func_<name>=no` to the target configure. Check for\n  more with a compile probe:\n  `xcrun --sdk iphonesimulator clang -target arm64-apple-ios17.0-simulator -isysroot <sdk> -c t.c`\n  where t.c calls the function after including the SDK headers.\n- First launch may show a local-network permission alert; dismiss it via Simulator UI.\n- The app opens to a \"Logseq / Sign in\" screen (Cognito hosted UI); going past it\n  requires credentials.\n- `duniverse/` pulls only the lockfile dirs (129). The `logseq/*` pins NOT vendored\n  (`datascript-ocaml`, `lg`, `lui`, `mldoc`, `persistent-sorted-set-ocaml`,\n  `signal-lg`) must be cloned manually into `duniverse/` at the SHAs listed in\n  `logseq.opam` — same loop as `.github/workflows/e2e.yml`. A fresh\n  `opam-monorepo pull` wipes these dirs, so re-clone them after each pull.\n- `scripts/build-mobile-ocaml.sh` regenerates `_build/dune-workspace.mobile` from\n  `dune-workspace.mobile`; set `LOGSEQ_OPAM_SWITCH=5.5.0` when running outside\n  `opam exec`.\n\n## Sheet interaction checks\n\n- Follow the existing journal calendar sheet for compact utility presentations. Result-view filter and sort sheets should open partially, with expansion available for longer lists (`medium,large` in the LUI wire format), and retain native navigation actions and swipe dismissal.\n- The custom Logseq palette must reach the complete modal surface, including navigation, list background, and grouped rows. LUI sheets render outside the scoped node tree; propagate the ancestor-resolved semantic colors into their content. Avoid unconditional system grouped backgrounds when a theme supplies a background.\n- Use a simulator runtime check to inspect the actual presented frame and screenshot colors in both appearances. For dark Logseq settings, the surrounding sheet background should match the graph background token (`#002D38`), with themed elevated rows. Also exercise Cancel, Done, and scrolling without changing filter/sort semantics.\n- Use `apple/Tests/UI/run-simulator-runtime-check.py` for native checks; do not run `swift test` in this repository.\n\n## Maestro e2e (test-ios-e2e-suite.sh)\n- Install Maestro: `curl -fsSL https://get.maestro.mobile.dev | bash` → `~/.maestro/bin`.\n- The e2e flows hit the app's sync server at `http://127.0.0.1:8787`. That server is\n  `deps/db-sync` in the `logseq` repo, and it MUST run from the\n  `feature/native-mobile-app` branch (the canonical `../logseq-1` checkout) — the app\n  requires `schema-version` in the `/sync/<id>/snapshot/download` response, which only\n  exists there (`main` returns without it → \"Add sync graph\" fails with\n  `NSURLErrorDomain Code=-1017`). Setup:\n  `cd ../logseq-1/deps/db-sync && pnpm install && clojure -M:cljs release db-sync-node`\n  (needs `JAVA_HOME=$(/usr/libexec/java_home -v 21)`), then\n  `DB_SYNC_PORT=8787 DB_SYNC_DATA_DIR=~/db-sync-data ./start.sh`;\n  health check `curl http://127.0.0.1:8787/health`.\n- Run: `LOGSEQ_IOS_SKIP_BUILD=1 LOGSEQ_E2E_USERNAME=<u> LOGSEQ_E2E_PASSWORD=<p> ./scripts/test-ios-e2e-suite.sh smoke`\n  (4 flows: capture-responsive, cold-start-composer, search-status-regression, sidebar).\n- `scripts/test-ios-e2e.sh` wipes the app data container between flows; `<container>/tmp`\n  must be recreated (the script does `mkdir -p`) or the OCaml core crashes writing the\n  initial graph snapshot via `Filename.temp_file` (`Sys_error ...tmp/logseq-initial-*.snapshot`).\n\n## Devin Secrets Needed\n- `LOGSEQ_TEST_USERNAME` / `LOGSEQ_TEST_PASSWORD` for hosted sign-in and e2e.\n",".agents/skills/testing-ocaml-core-linux/SKILL.md":"---\nname: testing-ocaml-core-linux\ndescription: Build and run the OCaml core test gate on Linux (opam deps, duniverse restore, lg prefix cache + dune shared cache, parallel test-chunk layout in shared/test/dune).\n---\n\n# Logseq OCaml core testing on Linux\n\nThe only Linux-runnable surface is the OCaml core in `shared/`. The gate is:\n\n```sh\neval $(opam env)          # 'default' switch here; README documents 5.5.0\ndune build @shared/native/runtest\n```\n\nNever `swift test` — it hangs on Linux.\n\n## Cold-build performance knobs\n\nTwo layered caches make `rm -rf _build` rebuilds fast; keep both warm:\n\n- `Logseq/.lg-cache/` — lg's content-addressed compile cache, outside `_build`,\n  survives clean builds. Prefix keys are recorded in each `*.state` artifact\n  (provenance key, lg >= the cache-fix revision pinned in `logseq.opam`);\n  do not digest state bytes.\n- Dune shared cache — off by default. Enable per machine in\n  `~/.config/dune/config`:\n\n  ```\n  (lang dune 3.0)\n  (cache enabled)\n  ```\n\n  Restores all builtin-rule artifacts (vendored deps, generated-module cmx)\n  on a cold `_build`. The `@runtest` action itself replays from cache when\n  inputs are unchanged.\n\nExpected on an 8-core box: ~40s cold without dune cache, ~13s with it\n(11.6s is the test run — a user rule, only skipped when fully replayed).\nA cold build where `.lg-cache` is ALSO empty recompiles every cljc (~4min).\n\n## Test target layout (shared/test/dune)\n\n- `lg-native-cmi-deps` alias (also in `shared/native/dune`) forces vendored\n  duniverse cmis to exist before lg runs; without it lg falls back to\n  same-named opam cmis and fails with \"inconsistent assumptions\".\n- `logseq_lui_test_base` — chunk compiled off\n  `../native/logseq_lg_core_native.state` (emitted by the core rule's\n  `--emit-state`), emits `include Logseq_lg_core_native` + literal/lui/\n  app/lg-test framework.\n- `logseq_lui_test_p1..p8` — 41 test namespaces as independent chunks\n  off `logseq_lui_test_base.state` (`--compile-files-chunk-from` +\n  `--prefix-interface` pointing at the base cmi). Add new test files to a\n  chunk (or a new chunk) — they compile in parallel.\n- Generated chunk modules must be listed on a LIBRARY (`logseq_lui_test_parts`,\n  `wrapped false`): dune does not emit compile rules for generated modules on\n  an executable. The runner exe needs `(link_flags -linkall)` — test\n  registration is initializer side-effects that dead-stripping drops.\n- `logseq_lui_test_z` is the last module alphabetically: it carries\n  `run.cljc`, which must run after all chunk registrations.\n\n## Environment restore (if duniverse/ is missing)\n\n`duniverse/` is gitignored. Restore per `logseq.opam.locked`: clone the\nopam source trees for each vendored package at the locked commit (private\nrepos lg/lui/signal-lg need `LOGSEQ_GITHUB_PAT`). `duniverse/lg` must match the\nlg pin in `logseq.opam` — `%{bin:lg}` resolves to the vendored copy.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/logseq/mobile/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Logseq\n\nLogseq uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`.\n\n## Testing\n\n- Do NOT run `swift test` (xctest). It hangs indefinitely in this\n  environment (an async Swift Testing case blocks on an XCTWaiter that never\n  finishes), wasting many minutes per run. Do not run it.\n- Validate OCaml core changes with `dune build @shared/native/runtest`.\n- If a Swift compile check is needed, use `swift build --package-path apple` (build only, no test\n  run) with sandbox disabled; SwiftPM's own sandbox conflicts with the agent\n  sandbox.\n\n## Build system\n\n- Use `dune build @shared/native/runtest` for core validation. The mobile entry object\n  also needs platform libraries and FFI symbols supplied by the mobile build.\n  Crypto protocol handling lives in `shared/src/logseq/core/platform_crypto.ml`.\n  The mobile-only `logseq_crypto_call` FFI declaration lives in\n  `shared/src/logseq/native_crypto.ml` so CLI builds do not require mobile symbols.\n- Mobile OCaml builds use the thin `scripts/build-mobile-ocaml.sh` Dune wrapper.\n  Native module membership lives in `shared/native/dune_modules/*.sexp`. Core sources\n  live in `shared/src/logseq/core`; adding one needs no per-file rule.\n\n## Cursor Cloud specific instructions\n\nCloud Agent VMs are Linux. They cannot run Xcode, the iOS simulator, or `swift test`. Do not try to start those from this environment.\n\nThe Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app's default API is `https://api.logseq.io`. Local sync testing can explicitly override it with `http://127.0.0.1:8787` from the separate Logseq server repository.\n\n### OCaml core\n\nUse the `5.5.0` opam switch (create it if needed with `opam switch create 5.5.0`):\n\n```sh\neval $(opam env --switch=5.5.0)\ndune runtest\n```\n\n`dune runtest` is the lint/test/build gate here. `dune build` of `logseq_mobile_entry` looks for SQLite via a Homebrew path in `shared/native/dune`; on Linux, either skip that executable or set `LIBRARY_PATH` to your system SQLite lib dir (e.g. `/usr/lib/x86_64-linux-gnu` on Debian/Ubuntu) first.\n\n`opam install . --deps-only` does not apply nested pins from `datascript-ocaml-native`. Pin these first (idempotent):\n\n```sh\nopam pin add -n -y melange-edn-core git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-edn-native git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-transit-core git+https://github.com/logseq/melange-transit.git#main\nopam pin add -n -y melange-transit-native git+https://github.com/logseq/melange-transit.git#main\nopam install . --deps-only --yes --with-test\n```\n\n`opam init` on this VM must use `--disable-sandboxing`. New shells need `eval $(opam env --switch=5.5.0)` unless `.bashrc` already loads it.\n\nA representative core action is the Swift FFI RPC `dispatch` / `send`, which optimistic-captures a journal block (see `shared/test/logseq/rpc_test.ml` and `dune build @shared/native/runtest`).\n\n- Avoid O(n²) `List` patterns such as `List.concat` and repeated `List.append` on large sequences; when the project already depends on the `rrbvec` package, use `Rrbvec` vectors instead.\n\n### iOS / Android\n\nOn a Mac, follow `README.md`: open `apple/Project.xcworkspace`, run the `Logseq App` scheme. Native core builds (`scripts/build-mobile-ios-*.sh`, `scripts/build-android-native.sh`) bootstrap their own cross toolchains under `_build/` via the `scripts/bootstrap-*.sh` helpers. Do not start Android emulators or Maestro from Cloud Agent unless that stack is explicitly in scope.\n","isInternal":false,"tokens":967,"sizeBytes":3699},{"name":"SKILL.md","path":".agents/skills/testing-ios-simulator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/logseq/mobile/HEAD/.agents/skills/testing-ios-simulator/SKILL.md","title":"testing-ios-simulator","category":"anthropic-skill","format":"markdown","content":"---\nname: testing-ios-simulator\ndescription: Build and launch the Logseq iOS app in an iOS simulator on macOS arm64 (Xcode + cross OCaml toolchain), including the iOS SDK function-detection pitfalls in bootstrap-ios-ocaml.sh.\n---\n\n# Logseq iOS Simulator Build & Launch\n\n## Prerequisites\n- macOS arm64 with Xcode installed (`xcodebuild -version` works).\n- opam switch `5.5.0` with dune (`opam exec --switch=5.5.0 -- dune --version`).\n- An iOS simulator: `xcrun simctl list devices available | grep iPhone`; boot one with\n  `xcrun simctl boot <UDID>`.\n\n## Build steps\n1. `scripts/bootstrap-ios-ocaml.sh simulator` — builds host + cross OCaml 5.5.0 under\n   `_build/apple-toolchains/ios/` (long first run; stamps skip rebuilds).\n2. `scripts/build-mobile-ios-simulator.sh` — builds `shared/native/logseq_mobile_entry.exe.o`\n   via dune context `ios_simulator`, then `swift build` (product `LogseqShell`),\n   xcodebuild for the share/widget extensions, and assembles+codesigns\n   `.build/Logseq.app`. Note: the script can exit non-zero at the end even when all\n   artifacts are produced correctly — re-running it (incremental) and checking for\n   `.build/Logseq.app/Logseq` is the practical check.\n3. `xcrun simctl install booted .build/Logseq.app`\n4. `xcrun simctl launch booted com.logseq.logseq` → prints `com.logseq.logseq: <pid>`;\n   verify the process stays alive via\n   `xcrun simctl spawn booted launchctl list | grep logseq`.\n5. Screenshot: `xcrun simctl io booted screenshot out.png`.\n\n## Pitfalls\n- `bootstrap-ios-ocaml.sh` host `./configure` must pass `--without-zstd`, else\n  zstd-compressed .cmi files break the LG toolchain later (LG2000 errors).\n- Cross-compiling OCaml for iOS: configure's link-only `AC_CHECK_FUNC` detects symbols\n  (pipe2, dup3, accept4, execvpe, prctl, secure_getenv, __secure_getenv) that link but\n  are NOT declared in the iOS SDK headers → \"call to undeclared function\" errors under\n  modern clang. Fix by passing `ac_cv_func_<name>=no` to the target configure. Check for\n  more with a compile probe:\n  `xcrun --sdk iphonesimulator clang -target arm64-apple-ios17.0-simulator -isysroot <sdk> -c t.c`\n  where t.c calls the function after including the SDK headers.\n- First launch may show a local-network permission alert; dismiss it via Simulator UI.\n- The app opens to a \"Logseq / Sign in\" screen (Cognito hosted UI); going past it\n  requires credentials.\n- `duniverse/` pulls only the lockfile dirs (129). The `logseq/*` pins NOT vendored\n  (`datascript-ocaml`, `lg`, `lui`, `mldoc`, `persistent-sorted-set-ocaml`,\n  `signal-lg`) must be cloned manually into `duniverse/` at the SHAs listed in\n  `logseq.opam` — same loop as `.github/workflows/e2e.yml`. A fresh\n  `opam-monorepo pull` wipes these dirs, so re-clone them after each pull.\n- `scripts/build-mobile-ocaml.sh` regenerates `_build/dune-workspace.mobile` from\n  `dune-workspace.mobile`; set `LOGSEQ_OPAM_SWITCH=5.5.0` when running outside\n  `opam exec`.\n\n## Sheet interaction checks\n\n- Follow the existing journal calendar sheet for compact utility presentations. Result-view filter and sort sheets should open partially, with expansion available for longer lists (`medium,large` in the LUI wire format), and retain native navigation actions and swipe dismissal.\n- The custom Logseq palette must reach the complete modal surface, including navigation, list background, and grouped rows. LUI sheets render outside the scoped node tree; propagate the ancestor-resolved semantic colors into their content. Avoid unconditional system grouped backgrounds when a theme supplies a background.\n- Use a simulator runtime check to inspect the actual presented frame and screenshot colors in both appearances. For dark Logseq settings, the surrounding sheet background should match the graph background token (`#002D38`), with themed elevated rows. Also exercise Cancel, Done, and scrolling without changing filter/sort semantics.\n- Use `apple/Tests/UI/run-simulator-runtime-check.py` for native checks; do not run `swift test` in this repository.\n\n## Maestro e2e (test-ios-e2e-suite.sh)\n- Install Maestro: `curl -fsSL https://get.maestro.mobile.dev | bash` → `~/.maestro/bin`.\n- The e2e flows hit the app's sync server at `http://127.0.0.1:8787`. That server is\n  `deps/db-sync` in the `logseq` repo, and it MUST run from the\n  `feature/native-mobile-app` branch (the canonical `../logseq-1` checkout) — the app\n  requires `schema-version` in the `/sync/<id>/snapshot/download` response, which only\n  exists there (`main` returns without it → \"Add sync graph\" fails with\n  `NSURLErrorDomain Code=-1017`). Setup:\n  `cd ../logseq-1/deps/db-sync && pnpm install && clojure -M:cljs release db-sync-node`\n  (needs `JAVA_HOME=$(/usr/libexec/java_home -v 21)`), then\n  `DB_SYNC_PORT=8787 DB_SYNC_DATA_DIR=~/db-sync-data ./start.sh`;\n  health check `curl http://127.0.0.1:8787/health`.\n- Run: `LOGSEQ_IOS_SKIP_BUILD=1 LOGSEQ_E2E_USERNAME=<u> LOGSEQ_E2E_PASSWORD=<p> ./scripts/test-ios-e2e-suite.sh smoke`\n  (4 flows: capture-responsive, cold-start-composer, search-status-regression, sidebar).\n- `scripts/test-ios-e2e.sh` wipes the app data container between flows; `<container>/tmp`\n  must be recreated (the script does `mkdir -p`) or the OCaml core crashes writing the\n  initial graph snapshot via `Filename.temp_file` (`Sys_error ...tmp/logseq-initial-*.snapshot`).\n\n## Devin Secrets Needed\n- `LOGSEQ_TEST_USERNAME` / `LOGSEQ_TEST_PASSWORD` for hosted sign-in and e2e.\n","frontmatter":{"name":"testing-ios-simulator","description":"Build and launch the Logseq iOS app in an iOS simulator on macOS arm64 (Xcode + cross OCaml toolchain), including the iOS SDK function-detection pitfalls in bootstrap-ios-ocaml.sh."},"isInternal":false,"tokens":1455,"sizeBytes":5468},{"name":"SKILL.md","path":".agents/skills/testing-ocaml-core-linux/SKILL.md","rawUrl":"https://raw.githubusercontent.com/logseq/mobile/HEAD/.agents/skills/testing-ocaml-core-linux/SKILL.md","title":"testing-ocaml-core-linux","category":"anthropic-skill","format":"markdown","content":"---\nname: testing-ocaml-core-linux\ndescription: Build and run the OCaml core test gate on Linux (opam deps, duniverse restore, lg prefix cache + dune shared cache, parallel test-chunk layout in shared/test/dune).\n---\n\n# Logseq OCaml core testing on Linux\n\nThe only Linux-runnable surface is the OCaml core in `shared/`. The gate is:\n\n```sh\neval $(opam env)          # 'default' switch here; README documents 5.5.0\ndune build @shared/native/runtest\n```\n\nNever `swift test` — it hangs on Linux.\n\n## Cold-build performance knobs\n\nTwo layered caches make `rm -rf _build` rebuilds fast; keep both warm:\n\n- `Logseq/.lg-cache/` — lg's content-addressed compile cache, outside `_build`,\n  survives clean builds. Prefix keys are recorded in each `*.state` artifact\n  (provenance key, lg >= the cache-fix revision pinned in `logseq.opam`);\n  do not digest state bytes.\n- Dune shared cache — off by default. Enable per machine in\n  `~/.config/dune/config`:\n\n  ```\n  (lang dune 3.0)\n  (cache enabled)\n  ```\n\n  Restores all builtin-rule artifacts (vendored deps, generated-module cmx)\n  on a cold `_build`. The `@runtest` action itself replays from cache when\n  inputs are unchanged.\n\nExpected on an 8-core box: ~40s cold without dune cache, ~13s with it\n(11.6s is the test run — a user rule, only skipped when fully replayed).\nA cold build where `.lg-cache` is ALSO empty recompiles every cljc (~4min).\n\n## Test target layout (shared/test/dune)\n\n- `lg-native-cmi-deps` alias (also in `shared/native/dune`) forces vendored\n  duniverse cmis to exist before lg runs; without it lg falls back to\n  same-named opam cmis and fails with \"inconsistent assumptions\".\n- `logseq_lui_test_base` — chunk compiled off\n  `../native/logseq_lg_core_native.state` (emitted by the core rule's\n  `--emit-state`), emits `include Logseq_lg_core_native` + literal/lui/\n  app/lg-test framework.\n- `logseq_lui_test_p1..p8` — 41 test namespaces as independent chunks\n  off `logseq_lui_test_base.state` (`--compile-files-chunk-from` +\n  `--prefix-interface` pointing at the base cmi). Add new test files to a\n  chunk (or a new chunk) — they compile in parallel.\n- Generated chunk modules must be listed on a LIBRARY (`logseq_lui_test_parts`,\n  `wrapped false`): dune does not emit compile rules for generated modules on\n  an executable. The runner exe needs `(link_flags -linkall)` — test\n  registration is initializer side-effects that dead-stripping drops.\n- `logseq_lui_test_z` is the last module alphabetically: it carries\n  `run.cljc`, which must run after all chunk registrations.\n\n## Environment restore (if duniverse/ is missing)\n\n`duniverse/` is gitignored. Restore per `logseq.opam.locked`: clone the\nopam source trees for each vendored package at the locked commit (private\nrepos lg/lui/signal-lg need `LOGSEQ_GITHUB_PAT`). `duniverse/lg` must match the\nlg pin in `logseq.opam` — `%{bin:lg}` resolves to the vendored copy.\n","frontmatter":{"name":"testing-ocaml-core-linux","description":"Build and run the OCaml core test gate on Linux (opam deps, duniverse restore, lg prefix cache + dune shared cache, parallel test-chunk layout in shared/test/dune)."},"isInternal":false,"tokens":783,"sizeBytes":2913}],"systemPromptSnippet":"<yakaai_skills repo=\"logseq/mobile\">\n<!-- File: AGENTS.md (Tokens: ~967 | Category: root-instruction) -->\n# Logseq\n\nLogseq uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`.\n\n## Testing\n\n- Do NOT run `swift test` (xctest). It hangs indefinitely in this\n  environment (an async Swift Testing case blocks on an XCTWaiter that never\n  finishes), wasting many minutes per run. Do not run it.\n- Validate OCaml core changes with `dune build @shared/native/runtest`.\n- If a Swift compile check is needed, use `swift build --package-path apple` (build only, no test\n  run) with sandbox disabled; SwiftPM's own sandbox conflicts with the agent\n  sandbox.\n\n## Build system\n\n- Use `dune build @shared/native/runtest` for core validation. The mobile entry object\n  also needs platform libraries and FFI symbols supplied by the mobile build.\n  Crypto protocol handling lives in `shared/src/logseq/core/platform_crypto.ml`.\n  The mobile-only `logseq_crypto_call` FFI declaration lives in\n  `shared/src/logseq/native_crypto.ml` so CLI builds do not require mobile symbols.\n- Mobile OCaml builds use the thin `scripts/build-mobile-ocaml.sh` Dune wrapper.\n  Native module membership lives in `shared/native/dune_modules/*.sexp`. Core sources\n  live in `shared/src/logseq/core`; adding one needs no per-file rule.\n\n## Cursor Cloud specific instructions\n\nCloud Agent VMs are Linux. They cannot run Xcode, the iOS simulator, or `swift test`. Do not try to start those from this environment.\n\nThe Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app's default API is `https://api.logseq.io`. Local sync testing can explicitly override it with `http://127.0.0.1:8787` from the separate Logseq server repository.\n\n### OCaml core\n\nUse the `5.5.0` opam switch (create it if needed with `opam switch create 5.5.0`):\n\n```sh\neval $(opam env --switch=5.5.0)\ndune runtest\n```\n\n`dune runtest` is the lint/test/build gate here. `dune build` of `logseq_mobile_entry` looks for SQLite via a Homebrew path in `shared/native/dune`; on Linux, either skip that executable or set `LIBRARY_PATH` to your system SQLite lib dir (e.g. `/usr/lib/x86_64-linux-gnu` on Debian/Ubuntu) first.\n\n`opam install . --deps-only` does not apply nested pins from `datascript-ocaml-native`. Pin these first (idempotent):\n\n```sh\nopam pin add -n -y melange-edn-core git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-edn-native git+https://github.com/logseq/melange-edn.git#main\nopam pin add -n -y melange-transit-core git+https://github.com/logseq/melange-transit.git#main\nopam pin add -n -y melange-transit-native git+https://github.com/logseq/melange-transit.git#main\nopam install . --deps-only --yes --with-test\n```\n\n`opam init` on this VM must use `--disable-sandboxing`. New shells need `eval $(opam env --switch=5.5.0)` unless `.bashrc` already loads it.\n\nA representative core action is the Swift FFI RPC `dispatch` / `send`, which optimistic-captures a journal block (see `shared/test/logseq/rpc_test.ml` and `dune build @shared/native/runtest`).\n\n- Avoid O(n²) `List` patterns such as `List.concat` and repeated `List.append` on large sequences; when the project already depends on the `rrbvec` package, use `Rrbvec` vectors instead.\n\n### iOS / Android\n\nOn a Mac, follow `README.md`: open `apple/Project.xcworkspace`, run the `Logseq App` scheme. Native core builds (`scripts/build-mobile-ios-*.sh`, `scripts/build-android-native.sh`) bootstrap their own cross toolchains under `_build/` via the `scripts/bootstrap-*.sh` helpers. Do not start Android emulators or Maestro from Cloud Agent unless that stack is explicitly in scope.\n\n<!-- File: .agents/skills/testing-ios-simulator/SKILL.md (Tokens: ~1455 | Category: anthropic-skill) -->\n---\nname: testing-ios-simulator\ndescription: Build and launch the Logseq iOS app in an iOS simulator on macOS arm64 (Xcode + cross OCaml toolchain), including the iOS SDK function-detection pitfalls in bootstrap-ios-ocaml.sh.\n---\n\n# Logseq iOS Simulator Build & Launch\n\n## Prerequisites\n- macOS arm64 with Xcode installed (`xcodebuild -version` works).\n- opam switch `5.5.0` with dune (`opam exec --switch=5.5.0 -- dune --version`).\n- An iOS simulator: `xcrun simctl list devices available | grep iPhone`; boot one with\n  `xcrun simctl boot <UDID>`.\n\n## Build steps\n1. `scripts/bootstrap-ios-ocaml.sh simulator` — builds host + cross OCaml 5.5.0 under\n   `_build/apple-toolchains/ios/` (long first run; stamps skip rebuilds).\n2. `scripts/build-mobile-ios-simulator.sh` — builds `shared/native/logseq_mobile_entry.exe.o`\n   via dune context `ios_simulator`, then `swift build` (product `LogseqShell`),\n   xcodebuild for the share/widget extensions, and assembles+codesigns\n   `.build/Logseq.app`. Note: the script can exit non-zero at the end even when all\n   artifacts are produced correctly — re-running it (incremental) and checking for\n   `.build/Logseq.app/Logseq` is the practical check.\n3. `xcrun simctl install booted .build/Logseq.app`\n4. `xcrun simctl launch booted com.logseq.logseq` → prints `com.logseq.logseq: <pid>`;\n   verify the process stays alive via\n   `xcrun simctl spawn booted launchctl list | grep logseq`.\n5. Screenshot: `xcrun simctl io booted screenshot out.png`.\n\n## Pitfalls\n- `bootstrap-ios-ocaml.sh` host `./configure` must pass `--without-zstd`, else\n  zstd-compressed .cmi files break the LG toolchain later (LG2000 errors).\n- Cross-compiling OCaml for iOS: configure's link-only `AC_CHECK_FUNC` detects symbols\n  (pipe2, dup3, accept4, execvpe, prctl, secure_getenv, __secure_getenv) that link but\n  are NOT declared in the iOS SDK headers → \"call to undeclared function\" errors under\n  modern clang. Fix by passing `ac_cv_func_<name>=no` to the target configure. Check for\n  more with a compile probe:\n  `xcrun --sdk iphonesimulator clang -target arm64-apple-ios17.0-simulator -isysroot <sdk> -c t.c`\n  where t.c calls the function after including the SDK headers.\n- First launch may show a local-network permission alert; dismiss it via Simulator UI.\n- The app opens to a \"Logseq / Sign in\" screen (Cognito hosted UI); going past it\n  requires credentials.\n- `duniverse/` pulls only the lockfile dirs (129). The `logseq/*` pins NOT vendored\n  (`datascript-ocaml`, `lg`, `lui`, `mldoc`, `persistent-sorted-set-ocaml`,\n  `signal-lg`) must be cloned manually into `duniverse/` at the SHAs listed in\n  `logseq.opam` — same loop as `.github/workflows/e2e.yml`. A fresh\n  `opam-monorepo pull` wipes these dirs, so re-clone them after each pull.\n- `scripts/build-mobile-ocaml.sh` regenerates `_build/dune-workspace.mobile` from\n  `dune-workspace.mobile`; set `LOGSEQ_OPAM_SWITCH=5.5.0` when running outside\n  `opam exec`.\n\n## Sheet interaction checks\n\n- Follow the existing journal calendar sheet for compact utility presentations. Result-view filter and sort sheets should open partially, with expansion available for longer lists (`medium,large` in the LUI wire format), and retain native navigation actions and swipe dismissal.\n- The custom Logseq palette must reach the complete modal surface, including navigation, list background, and grouped rows. LUI sheets render outside the scoped node tree; propagate the ancestor-resolved semantic colors into their content. Avoid unconditional system grouped backgrounds when a theme supplies a background.\n- Use a simulator runtime check to inspect the actual presented frame and screenshot colors in both appearances. For dark Logseq settings, the surrounding sheet background should match the graph background token (`#002D38`), with themed elevated rows. Also exercise Cancel, Done, and scrolling without changing filter/sort semantics.\n- Use `apple/Tests/UI/run-simulator-runtime-check.py` for native checks; do not run `swift test` in this repository.\n\n## Maestro e2e (test-ios-e2e-suite.sh)\n- Install Maestro: `curl -fsSL https://get.maestro.mobile.dev | bash` → `~/.maestro/bin`.\n- The e2e flows hit the app's sync server at `http://127.0.0.1:8787`. That server is\n  `deps/db-sync` in the `logseq` repo, and it MUST run from the\n  `feature/native-mobile-app` branch (the canonical `../logseq-1` checkout) — the app\n  requires `schema-version` in the `/sync/<id>/snapshot/download` response, which only\n  exists there (`main` returns without it → \"Add sync graph\" fails with\n  `NSURLErrorDomain Code=-1017`). Setup:\n  `cd ../logseq-1/deps/db-sync && pnpm install && clojure -M:cljs release db-sync-node`\n  (needs `JAVA_HOME=$(/usr/libexec/java_home -v 21)`), then\n  `DB_SYNC_PORT=8787 DB_SYNC_DATA_DIR=~/db-sync-data ./start.sh`;\n  health check `curl http://127.0.0.1:8787/health`.\n- Run: `LOGSEQ_IOS_SKIP_BUILD=1 LOGSEQ_E2E_USERNAME=<u> LOGSEQ_E2E_PASSWORD=<p> ./scripts/test-ios-e2e-suite.sh smoke`\n  (4 flows: capture-responsive, cold-start-composer, search-status-regression, sidebar).\n- `scripts/test-ios-e2e.sh` wipes the app data container between flows; `<container>/tmp`\n  must be recreated (the script does `mkdir -p`) or the OCaml core crashes writing the\n  initial graph snapshot via `Filename.temp_file` (`Sys_error ...tmp/logseq-initial-*.snapshot`).\n\n## Devin Secrets Needed\n- `LOGSEQ_TEST_USERNAME` / `LOGSEQ_TEST_PASSWORD` for hosted sign-in and e2e.\n\n<!-- File: .agents/skills/testing-ocaml-core-linux/SKILL.md (Tokens: ~783 | Category: anthropic-skill) -->\n---\nname: testing-ocaml-core-linux\ndescription: Build and run the OCaml core test gate on Linux (opam deps, duniverse restore, lg prefix cache + dune shared cache, parallel test-chunk layout in shared/test/dune).\n---\n\n# Logseq OCaml core testing on Linux\n\nThe only Linux-runnable surface is the OCaml core in `shared/`. The gate is:\n\n```sh\neval $(opam env)          # 'default' switch here; README documents 5.5.0\ndune build @shared/native/runtest\n```\n\nNever `swift test` — it hangs on Linux.\n\n## Cold-build performance knobs\n\nTwo layered caches make `rm -rf _build` rebuilds fast; keep both warm:\n\n- `Logseq/.lg-cache/` — lg's content-addressed compile cache, outside `_build`,\n  survives clean builds. Prefix keys are recorded in each `*.state` artifact\n  (provenance key, lg >= the cache-fix revision pinned in `logseq.opam`);\n  do not digest state bytes.\n- Dune shared cache — off by default. Enable per machine in\n  `~/.config/dune/config`:\n\n  ```\n  (lang dune 3.0)\n  (cache enabled)\n  ```\n\n  Restores all builtin-rule artifacts (vendored deps, generated-module cmx)\n  on a cold `_build`. The `@runtest` action itself replays from cache when\n  inputs are unchanged.\n\nExpected on an 8-core box: ~40s cold without dune cache, ~13s with it\n(11.6s is the test run — a user rule, only skipped when fully replayed).\nA cold build where `.lg-cache` is ALSO empty recompiles every cljc (~4min).\n\n## Test target layout (shared/test/dune)\n\n- `lg-native-cmi-deps` alias (also in `shared/native/dune`) forces vendored\n  duniverse cmis to exist before lg runs; without it lg falls back to\n  same-named opam cmis and fails with \"inconsistent assumptions\".\n- `logseq_lui_test_base` — chunk compiled off\n  `../native/logseq_lg_core_native.state` (emitted by the core rule's\n  `--emit-state`), emits `include Logseq_lg_core_native` + literal/lui/\n  app/lg-test framework.\n- `logseq_lui_test_p1..p8` — 41 test namespaces as independent chunks\n  off `logseq_lui_test_base.state` (`--compile-files-chunk-from` +\n  `--prefix-interface` pointing at the base cmi). Add new test files to a\n  chunk (or a new chunk) — they compile in parallel.\n- Generated chunk modules must be listed on a LIBRARY (`logseq_lui_test_parts`,\n  `wrapped false`): dune does not emit compile rules for generated modules on\n  an executable. The runner exe needs `(link_flags -linkall)` — test\n  registration is initializer side-effects that dead-stripping drops.\n- `logseq_lui_test_z` is the last module alphabetically: it carries\n  `run.cljc`, which must run after all chunk registrations.\n\n## Environment restore (if duniverse/ is missing)\n\n`duniverse/` is gitignored. Restore per `logseq.opam.locked`: clone the\nopam source trees for each vendored package at the locked commit (private\nrepos lg/lui/signal-lg need `LOGSEQ_GITHUB_PAT`). `duniverse/lg` must match the\nlg pin in `logseq.opam` — `%{bin:lg}` resolves to the vendored copy.\n</yakaai_skills>"}