python-delphi-lsp 2.2.0__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. {python_delphi_lsp-2.2.0/python_delphi_lsp.egg-info → python_delphi_lsp-2.3.0}/PKG-INFO +11 -3
  2. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/README.md +10 -2
  3. python_delphi_lsp-2.3.0/delphi_lsp/_version.py +1 -0
  4. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_cache.py +18 -0
  5. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_context.py +453 -183
  6. python_delphi_lsp-2.3.0/delphi_lsp/agent_metrics.py +179 -0
  7. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_protocol.py +4 -3
  8. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_relations.py +272 -26
  9. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_workspace.py +16 -3
  10. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/metrics.py +45 -7
  11. python_delphi_lsp-2.3.0/delphi_lsp/navigation_cache.py +134 -0
  12. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/preprocessor.py +56 -20
  13. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/pyproject.toml +1 -1
  14. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0/python_delphi_lsp.egg-info}/PKG-INFO +11 -3
  15. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/python_delphi_lsp.egg-info/SOURCES.txt +2 -0
  16. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_cache.py +5 -0
  17. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_context.py +259 -16
  18. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_metrics.py +36 -0
  19. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_protocol.py +31 -0
  20. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_relations.py +55 -0
  21. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_workspace.py +35 -0
  22. python_delphi_lsp-2.3.0/tests/test_navigation_cache.py +43 -0
  23. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_package_metadata.py +3 -3
  24. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_preprocessor.py +57 -1
  25. python_delphi_lsp-2.2.0/delphi_lsp/_version.py +0 -1
  26. python_delphi_lsp-2.2.0/delphi_lsp/agent_metrics.py +0 -82
  27. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/.github/workflows/ci.yml +0 -0
  28. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/LICENSE +0 -0
  29. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/MANIFEST.in +0 -0
  30. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/__init__.py +0 -0
  31. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_cli.py +0 -0
  32. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_layers.py +0 -0
  33. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/agent_templates.py +0 -0
  34. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/binary.py +0 -0
  35. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/comment_builder.py +0 -0
  36. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/consts.py +0 -0
  37. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/delphiast_lexer.py +0 -0
  38. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/delphiast_parser.py +0 -0
  39. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/delphiast_tokens.py +0 -0
  40. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/grammar.py +0 -0
  41. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/lark_builder.py +0 -0
  42. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/lark_tokens.py +0 -0
  43. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/lsp_server.py +0 -0
  44. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/nodes.py +0 -0
  45. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/parallel_outline.py +0 -0
  46. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/parser.py +0 -0
  47. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/parser_backend.py +0 -0
  48. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/progress.py +0 -0
  49. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/project_discovery.py +0 -0
  50. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/project_indexer.py +0 -0
  51. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/semantic.py +0 -0
  52. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/semantic_builder.py +0 -0
  53. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/source_reader.py +0 -0
  54. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/workspace.py +0 -0
  55. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/delphi_lsp/writer.py +0 -0
  56. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/opencode.json +0 -0
  57. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/python_delphi_lsp.egg-info/dependency_links.txt +0 -0
  58. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/python_delphi_lsp.egg-info/entry_points.txt +0 -0
  59. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/python_delphi_lsp.egg-info/requires.txt +0 -0
  60. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/python_delphi_lsp.egg-info/top_level.txt +0 -0
  61. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/audit_delphi_language_features.py +0 -0
  62. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/benchmark_github_corpus.py +0 -0
  63. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/benchmark_parallel_cache.py +0 -0
  64. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/bootstrap_vllm_codebase_skill_test.py +0 -0
  65. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/bootstrap_vllm_opencode_test.ps1 +0 -0
  66. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/bootstrap_vllm_opencode_test.py +0 -0
  67. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/bootstrap_vllm_opencode_test.sh +0 -0
  68. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/build_github_performance_corpus.py +0 -0
  69. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/check_ornith_cache.py +0 -0
  70. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/generate_progress_pdf.py +0 -0
  71. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/generate_release_evidence.py +0 -0
  72. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/ollama/ornith-lspctx.Modelfile +0 -0
  73. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/prepare_ornith_cache.py +0 -0
  74. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/run_opencode_lsp_probe.py +0 -0
  75. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/run_openrouter_github_e2e.py +0 -0
  76. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/start_ornith_vllm.sh +0 -0
  77. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/scripts/summarize_opencode_request_payloads.py +0 -0
  78. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/setup.cfg +0 -0
  79. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/corpora.performance.lock.json +0 -0
  80. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/DeprecatedOnConst.pas +0 -0
  81. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/VariantRecordFieldAttributes.pas +0 -0
  82. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/alignedrecords.pas +0 -0
  83. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/constset.pas +0 -0
  84. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/deprecatedtype.pas +0 -0
  85. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/dottedtypes.pas +0 -0
  86. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/endtoken.pas +0 -0
  87. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/experimentals.pas +0 -0
  88. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/externalfunction.pas +0 -0
  89. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/finalizationinitializationexports.pas +0 -0
  90. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/forwardoverloaded.pas +0 -0
  91. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/forwardwithoutsemicolon.pas +0 -0
  92. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/genericconstraints.pas +0 -0
  93. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/genericinterfacemethoddelegation.pas +0 -0
  94. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/implementsgenerictype.pas +0 -0
  95. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/include file2.inc +0 -0
  96. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/includefile.inc +0 -0
  97. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/includefile.pas +0 -0
  98. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/managedrecords.pas +0 -0
  99. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/messagemethod.pas +0 -0
  100. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/multiline.pas +0 -0
  101. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/nonalignedrecords.pas +0 -0
  102. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/numbers.pas +0 -0
  103. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/pointerchars.pas +0 -0
  104. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/properties.pas +0 -0
  105. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/strictvisibility.pas +0 -0
  106. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/tryexcept.pas +0 -0
  107. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/umlauts.pas +0 -0
  108. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/legacy_snippets/whitespacearoundifdefcondition.pas +0 -0
  109. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/library_demo.dpr +0 -0
  110. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/package_demo.dpk +0 -0
  111. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/program_demo.dpr +0 -0
  112. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_advanced.pas +0 -0
  113. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_attributes.pas +0 -0
  114. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_basic.pas +0 -0
  115. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_consumer.pas +0 -0
  116. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_generics.pas +0 -0
  117. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_inheritance.pas +0 -0
  118. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_math.pas +0 -0
  119. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_properties.pas +0 -0
  120. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_sections.pas +0 -0
  121. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_statements.pas +0 -0
  122. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_types.pas +0 -0
  123. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_unresolved.pas +0 -0
  124. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/fixtures/unit_with.pas +0 -0
  125. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_codebase.py +0 -0
  126. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_agent_worker.py +0 -0
  127. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_bootstrap_vllm_codebase_skill.py +0 -0
  128. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_bootstrap_vllm_opencode.py +0 -0
  129. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_delphiast_lexer.py +0 -0
  130. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_delphiast_native_compatibility.py +0 -0
  131. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_delphiast_parser.py +0 -0
  132. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_delphiast_semantic_compatibility.py +0 -0
  133. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_diagnostics.py +0 -0
  134. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_github_performance_corpus.py +0 -0
  135. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_language_feature_matrix.py +0 -0
  136. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_legacy_snippets.py +0 -0
  137. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_lsp_features.py +0 -0
  138. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_lsp_support.py +0 -0
  139. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_metrics.py +0 -0
  140. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_opencode_config.py +0 -0
  141. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_opencode_probe.py +0 -0
  142. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_opencode_request_payloads.py +0 -0
  143. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_openrouter_github_e2e.py +0 -0
  144. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_ornith_cache_prepare.py +0 -0
  145. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_parallel_outline.py +0 -0
  146. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_parser.py +0 -0
  147. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_parser_backends.py +0 -0
  148. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_progress.py +0 -0
  149. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_project_discovery.py +0 -0
  150. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_project_indexer.py +0 -0
  151. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_release_evidence.py +0 -0
  152. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_semantic.py +0 -0
  153. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_vllm_start_script.py +0 -0
  154. {python_delphi_lsp-2.2.0 → python_delphi_lsp-2.3.0}/tests/test_workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-delphi-lsp
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Python Delphi/Object Pascal parser, semantic indexer, and language server.
5
5
  Author: Dark Light
6
6
  License-Expression: MPL-2.0
@@ -42,7 +42,7 @@ Dynamic: license-file
42
42
 
43
43
  `python-delphi-lsp` parses Delphi/Object Pascal, builds semantic and project
44
44
  indexes, serves LSP, and provides bounded codebase navigation for agents.
45
- Version 2.2.0 is authored by Dark Light and supports Windows, macOS, and Linux.
45
+ Version 2.3.0 is authored by Dark Light and supports Windows, macOS, and Linux.
46
46
 
47
47
  ## Install and quick start
48
48
 
@@ -257,6 +257,13 @@ to measure it. If an automatic pool fails before accepting a result, one
257
257
  automatic serial fallback is attempted; explicit worker counts fail instead of
258
258
  silently changing the requested configuration.
259
259
 
260
+ Detached navigation shards are also stored as versioned, content-addressed JSON
261
+ under `.delphi-lsp/agent-cache/navigation-v1`. A restarted CLI or OpenCode cache
262
+ daemon reuses unchanged units without parsing them again. Source content,
263
+ conditional defines, or a shard-schema change produces a cache miss; malformed
264
+ or incompatible JSON is ignored and rebuilt. The disk cache contains no pickle
265
+ payloads and does not count against the retained-RAM budget.
266
+
260
267
  Cache prewarming builds the navigation registry directly without constructing
261
268
  an empty-query result, symbol cards, pagination, or JSON payloads. Up to sixteen
262
269
  recent ranked queries are retained in a small LRU so alternating CLI and
@@ -276,7 +283,8 @@ The daemon tracks a 30-minute idle timeout; idle state shows in JSON status (`ca
276
283
  Workspace state appears in status as `requests`, `warm_hits`, `rebuilds`, `invalidations`,
277
284
  `evictions`, and `cache_state`. Parallel prewarm status adds
278
285
  `workers_configured`, `workers_effective`, `parallel_files_completed`,
279
- `prewarm_seconds`, `parallel_seconds`, and `parallel_fallbacks`.
286
+ `prewarm_seconds`, `parallel_seconds`, `parallel_fallbacks`,
287
+ `navigation_disk_hits`, and `navigation_disk_misses`.
280
288
 
281
289
  Metadata is stored in `.delphi-lsp/agent-cache/daemon.json` with owner-only token and
282
290
  permissions (`daemon.json` mode 600 and parent 700). Do not copy or share this token
@@ -2,7 +2,7 @@
2
2
 
3
3
  `python-delphi-lsp` parses Delphi/Object Pascal, builds semantic and project
4
4
  indexes, serves LSP, and provides bounded codebase navigation for agents.
5
- Version 2.2.0 is authored by Dark Light and supports Windows, macOS, and Linux.
5
+ Version 2.3.0 is authored by Dark Light and supports Windows, macOS, and Linux.
6
6
 
7
7
  ## Install and quick start
8
8
 
@@ -217,6 +217,13 @@ to measure it. If an automatic pool fails before accepting a result, one
217
217
  automatic serial fallback is attempted; explicit worker counts fail instead of
218
218
  silently changing the requested configuration.
219
219
 
220
+ Detached navigation shards are also stored as versioned, content-addressed JSON
221
+ under `.delphi-lsp/agent-cache/navigation-v1`. A restarted CLI or OpenCode cache
222
+ daemon reuses unchanged units without parsing them again. Source content,
223
+ conditional defines, or a shard-schema change produces a cache miss; malformed
224
+ or incompatible JSON is ignored and rebuilt. The disk cache contains no pickle
225
+ payloads and does not count against the retained-RAM budget.
226
+
220
227
  Cache prewarming builds the navigation registry directly without constructing
221
228
  an empty-query result, symbol cards, pagination, or JSON payloads. Up to sixteen
222
229
  recent ranked queries are retained in a small LRU so alternating CLI and
@@ -236,7 +243,8 @@ The daemon tracks a 30-minute idle timeout; idle state shows in JSON status (`ca
236
243
  Workspace state appears in status as `requests`, `warm_hits`, `rebuilds`, `invalidations`,
237
244
  `evictions`, and `cache_state`. Parallel prewarm status adds
238
245
  `workers_configured`, `workers_effective`, `parallel_files_completed`,
239
- `prewarm_seconds`, `parallel_seconds`, and `parallel_fallbacks`.
246
+ `prewarm_seconds`, `parallel_seconds`, `parallel_fallbacks`,
247
+ `navigation_disk_hits`, and `navigation_disk_misses`.
240
248
 
241
249
  Metadata is stored in `.delphi-lsp/agent-cache/daemon.json` with owner-only token and
242
250
  permissions (`daemon.json` mode 600 and parent 700). Do not copy or share this token
@@ -0,0 +1 @@
1
+ __version__ = "2.3.0"
@@ -280,6 +280,18 @@ def _safe_metadata_path(root: str | Path, *, create: bool = False) -> Path:
280
280
  return result
281
281
 
282
282
 
283
+ def _safe_navigation_cache_path(root: str | Path, *, create: bool = False) -> Path:
284
+ parent = _safe_metadata_path(root, create=create).parent
285
+ result = parent / "navigation-v1"
286
+ if result.exists() and result.is_symlink():
287
+ raise CacheClientError("unsafe_metadata", "Navigation cache path is unsafe.")
288
+ if create:
289
+ result.mkdir(mode=0o700, exist_ok=True)
290
+ if os.name != "nt":
291
+ os.chmod(result, 0o700)
292
+ return result
293
+
294
+
283
295
  def _metadata_mapping(metadata: CacheMetadata) -> dict[str, object]:
284
296
  return {field.name: getattr(metadata, field.name) for field in fields(metadata)}
285
297
 
@@ -549,6 +561,10 @@ class _CacheService:
549
561
  workers=metadata.workers,
550
562
  worker_memory_budget_bytes=metadata.max_memory_bytes,
551
563
  revision_check_interval_seconds=_CACHE_REVISION_CHECK_INTERVAL_SECONDS,
564
+ navigation_cache_dir=_safe_navigation_cache_path(
565
+ metadata.root,
566
+ create=True,
567
+ ),
552
568
  )
553
569
  self.budget = CacheBudget(metadata.max_memory_bytes)
554
570
  self.stats = CacheStats()
@@ -648,6 +664,8 @@ class _CacheService:
648
664
  "prewarm_seconds": self.prewarm_seconds,
649
665
  "parallel_seconds": self.context.parallel_stats.elapsed_seconds,
650
666
  "parallel_fallbacks": self.stats.parallel_fallbacks,
667
+ "navigation_disk_hits": self.context.navigation_disk_hits,
668
+ "navigation_disk_misses": self.context.navigation_disk_misses,
651
669
  "idle_timeout": self.metadata.idle_timeout, "idle_remaining": max(0.0, self.metadata.idle_timeout - idle),
652
670
  "workspace_revision": self.last_revision,
653
671
  }