doc3gpp 0.2.1__tar.gz → 0.3.2__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 (561) hide show
  1. doc3gpp-0.3.2/.superpowers/sdd/.gitignore +2 -0
  2. doc3gpp-0.3.2/.superpowers/sdd/2026-09-24-spec-doc-metadata-and-portal-fix/final-fix-report.md +179 -0
  3. doc3gpp-0.3.2/.superpowers/sdd/2026-09-24-spec-doc-metadata-and-portal-fix/task-2-report.md +129 -0
  4. doc3gpp-0.3.2/.superpowers/sdd/2026-09-24-spec-doc-web-portal/final-fix-report.md +255 -0
  5. doc3gpp-0.3.2/.superpowers/sdd/2026-09-24-spec-doc-web-portal/task-2-report.md +62 -0
  6. doc3gpp-0.3.2/.superpowers/sdd/2026-09-25-spec-parsed-output/final-fix-report.md +129 -0
  7. doc3gpp-0.3.2/.superpowers/sdd/2026-09-25-spec-parsed-output/task-3-report.md +73 -0
  8. doc3gpp-0.3.2/.superpowers/sdd/2026-09-25-spec-parsed-output/task-4-report.md +90 -0
  9. doc3gpp-0.3.2/.superpowers/sdd/2026-09-25-spec-parsed-output/task-7-report.md +174 -0
  10. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/AGENTS.md +49 -48
  11. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/PKG-INFO +153 -141
  12. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/README.md +151 -138
  13. doc3gpp-0.3.2/docs/TODO.md +42 -0
  14. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/architecture.md +303 -67
  15. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/cli.md +285 -115
  16. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/code-map.md +67 -26
  17. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/conventions.md +11 -3
  18. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-22-remote-embedding-api.md +675 -0
  19. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-23-spec-doc-parse.md +1553 -0
  20. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-24-spec-doc-fetch-command-removal.md +380 -0
  21. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-24-spec-doc-metadata-and-portal-fix.md +911 -0
  22. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-24-tdoc-search-namespace.md +422 -0
  23. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-25-spec-doc-chunk-context.md +305 -0
  24. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-25-spec-doc-pagination.md +527 -0
  25. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-25-spec-parsed-output.md +772 -0
  26. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-26-unified-search-index.md +734 -0
  27. doc3gpp-0.3.2/docs/superpowers/plans/2026-09-27-mcp-stdio.md +923 -0
  28. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-22-remote-embedding-api-design.md +163 -0
  29. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-23-spec-doc-parse-design.md +296 -0
  30. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-24-spec-doc-fetch-command-removal-design.md +130 -0
  31. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-24-spec-doc-metadata-and-portal-fix-design.md +185 -0
  32. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-24-spec-doc-web-portal-design.md +338 -0
  33. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-24-tdoc-search-namespace-design.md +153 -0
  34. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-25-spec-doc-chunk-context-design.md +136 -0
  35. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-25-spec-doc-pagination-design.md +234 -0
  36. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-25-spec-parsed-output-design.md +125 -0
  37. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-26-unified-search-index-design.md +417 -0
  38. doc3gpp-0.3.2/docs/superpowers/specs/2026-09-27-mcp-stdio-design.md +209 -0
  39. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/web-server.md +137 -53
  40. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/pyproject.toml +4 -3
  41. doc3gpp-0.3.2/scripts/dev_run.sh +12 -0
  42. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/__init__.py +1 -1
  43. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/cli.py +920 -624
  44. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/cli_server.py +88 -23
  45. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/data/doc3gpp.toml.example +107 -49
  46. doc3gpp-0.3.2/src/doc3gpp/data/skills/doc3gpp/SKILL.md +64 -0
  47. doc3gpp-0.3.2/src/doc3gpp/models/index.py +101 -0
  48. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/jobs.py +4 -2
  49. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/schema_info.py +43 -2
  50. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/search.py +16 -5
  51. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/semantic_search.py +2 -2
  52. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/spec.py +16 -0
  53. doc3gpp-0.3.2/src/doc3gpp/models/spec_doc.py +125 -0
  54. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tdoc.py +2 -1
  55. doc3gpp-0.3.2/src/doc3gpp/models/unified_search.py +98 -0
  56. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/docx_converter.py +127 -1
  57. doc3gpp-0.3.2/src/doc3gpp/parsers/spec_doc.py +141 -0
  58. doc3gpp-0.3.2/src/doc3gpp/parsers/spec_doc_chunker.py +295 -0
  59. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/repository/protocols.py +285 -28
  60. doc3gpp-0.3.2/src/doc3gpp/scraping/spec_doc_source.py +73 -0
  61. doc3gpp-0.3.2/src/doc3gpp/services/embedding/__init__.py +11 -0
  62. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/embedding/chunker.py +2 -2
  63. doc3gpp-0.3.2/src/doc3gpp/services/embedding/remote_embedder.py +97 -0
  64. doc3gpp-0.3.2/src/doc3gpp/services/factory.py +820 -0
  65. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/search_service.py +18 -14
  66. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/semantic_reranker.py +9 -7
  67. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/semantic_search_service.py +31 -12
  68. doc3gpp-0.3.2/src/doc3gpp/services/spec_doc_index_service.py +167 -0
  69. doc3gpp-0.3.2/src/doc3gpp/services/spec_doc_search_facade.py +197 -0
  70. doc3gpp-0.3.2/src/doc3gpp/services/spec_doc_search_service.py +136 -0
  71. doc3gpp-0.3.2/src/doc3gpp/services/spec_doc_semantic_service.py +298 -0
  72. doc3gpp-0.3.2/src/doc3gpp/services/spec_doc_service.py +407 -0
  73. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/spec_service.py +45 -6
  74. doc3gpp-0.3.2/src/doc3gpp/services/tdoc_index_service.py +159 -0
  75. doc3gpp-0.3.2/src/doc3gpp/services/tdoc_search_facade.py +179 -0
  76. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/settings/config_writer.py +13 -1
  77. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/settings/schema.py +178 -45
  78. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/backends/sqlite.py +15 -7
  79. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/migrate.py +150 -24
  80. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/models.py +58 -0
  81. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/session.py +54 -3
  82. doc3gpp-0.3.2/src/doc3gpp/storage/db/specdata_base.py +13 -0
  83. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/jobs_sql.py +7 -2
  84. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/search_sql.py +5 -2
  85. doc3gpp-0.3.2/src/doc3gpp/storage/repositories/spec_doc_search_sql.py +508 -0
  86. doc3gpp-0.3.2/src/doc3gpp/storage/repositories/spec_doc_sql.py +416 -0
  87. doc3gpp-0.3.2/src/doc3gpp/storage/repositories/spec_doc_vector_sql.py +654 -0
  88. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/spec_sql.py +8 -10
  89. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tdoc_sql.py +59 -3
  90. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/vector_sql.py +138 -30
  91. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/app.py +74 -12
  92. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/deps.py +44 -3
  93. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/errors.py +81 -13
  94. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/mcp_server.py +277 -79
  95. doc3gpp-0.3.2/src/doc3gpp/web/mcp_stdio.py +71 -0
  96. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/render.py +99 -5
  97. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/__init__.py +4 -2
  98. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/jobs.py +71 -11
  99. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/landing.py +7 -2
  100. doc3gpp-0.3.2/src/doc3gpp/web/routes/search.py +230 -0
  101. doc3gpp-0.3.2/src/doc3gpp/web/routes/spec_docs.py +465 -0
  102. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/specs.py +6 -2
  103. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/state.py +45 -16
  104. doc3gpp-0.3.2/src/doc3gpp/web/static/js/spec_doc_parse.js +32 -0
  105. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/sync_hub.js +15 -6
  106. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/style.css +41 -0
  107. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/base.html +2 -2
  108. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/search_form.html +7 -21
  109. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/search_resource_tabs.html +4 -0
  110. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/search_results.html +4 -7
  111. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/search_results_table.html +8 -14
  112. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_chunks.html +56 -0
  113. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_search_form.html +36 -0
  114. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_search_results.html +22 -0
  115. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_search_results_table.html +60 -0
  116. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_show_results.html +78 -0
  117. doc3gpp-0.3.2/src/doc3gpp/web/templates/partials/spec_doc_toc_results.html +41 -0
  118. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/spec_filters.html +7 -0
  119. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/spec_results.html +2 -0
  120. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/search_results.html +8 -17
  121. doc3gpp-0.3.2/src/doc3gpp/web/templates/spec_doc_show.html +51 -0
  122. doc3gpp-0.3.2/src/doc3gpp/web/templates/spec_doc_toc.html +10 -0
  123. doc3gpp-0.3.2/src/doc3gpp/web/templates/spec_docs_search.html +24 -0
  124. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/spec_show.html +6 -0
  125. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/sync.html +29 -8
  126. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/workers/handlers.py +154 -2
  127. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/workers/job_worker.py +15 -0
  128. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/conftest.py +12 -3
  129. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/semantic_search_corpus.py +2 -2
  130. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_cli_server.py +54 -6
  131. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_config_init_cli_sqlite.py +18 -6
  132. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_mcp_end_to_end.py +737 -88
  133. doc3gpp-0.3.2/tests/integration/test_online_spec_doc_sync.py +103 -0
  134. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_filters.py +33 -5
  135. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_previews_per_column.py +32 -4
  136. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_query_sem_rerank.py +62 -86
  137. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_sem_end_to_end.py +9 -2
  138. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_spec_cli.py +103 -0
  139. doc3gpp-0.3.2/tests/integration/test_spec_doc_cli.py +61 -0
  140. doc3gpp-0.3.2/tests/integration/test_spec_doc_repo.py +178 -0
  141. doc3gpp-0.3.2/tests/integration/test_spec_doc_search_repo.py +479 -0
  142. doc3gpp-0.3.2/tests/integration/test_spec_doc_search_service.py +395 -0
  143. doc3gpp-0.3.2/tests/integration/test_spec_doc_service.py +299 -0
  144. doc3gpp-0.3.2/tests/integration/test_spec_doc_web.py +43 -0
  145. doc3gpp-0.3.2/tests/integration/test_spec_parsed_output.py +134 -0
  146. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_spec_sql.py +10 -0
  147. doc3gpp-0.3.2/tests/integration/test_sqlite_backend.py +67 -0
  148. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_sync_hub_end_to_end.py +21 -6
  149. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_sqlite.py +71 -0
  150. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_vector_index_lifecycle.py +158 -1
  151. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_vector_repo_get_min_distance.py +3 -2
  152. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_web_search_end_to_end.py +27 -21
  153. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cache_cli.py +4 -4
  154. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_chunker.py +2 -2
  155. doc3gpp-0.3.2/tests/unit/test_cli_search.py +739 -0
  156. doc3gpp-0.3.2/tests/unit/test_cli_search_sem.py +89 -0
  157. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cli_server_start.py +25 -16
  158. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cli_server_stubs.py +9 -17
  159. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cr_parser.py +17 -11
  160. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_db_reset_cli.py +15 -2
  161. doc3gpp-0.3.2/tests/unit/test_factory_semantic.py +179 -0
  162. doc3gpp-0.3.2/tests/unit/test_index_services.py +293 -0
  163. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_job_worker.py +152 -16
  164. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_jobs_sql.py +18 -0
  165. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_sync_tsg_validation.py +3 -7
  166. doc3gpp-0.3.2/tests/unit/test_packaging_semantic.py +117 -0
  167. doc3gpp-0.3.2/tests/unit/test_remote_embedder.py +109 -0
  168. doc3gpp-0.3.2/tests/unit/test_remote_embedding_settings.py +65 -0
  169. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_schema_info.py +31 -2
  170. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_search_service.py +69 -9
  171. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_semantic_search_service.py +12 -2
  172. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_semantic_settings.py +3 -3
  173. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_server_settings.py +3 -3
  174. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_services_factory.py +32 -1
  175. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_settings.py +1 -1
  176. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_settings_config_file.py +23 -9
  177. doc3gpp-0.3.2/tests/unit/test_spec_doc_blocks.py +97 -0
  178. doc3gpp-0.3.2/tests/unit/test_spec_doc_chunker.py +315 -0
  179. doc3gpp-0.3.2/tests/unit/test_spec_doc_models.py +82 -0
  180. doc3gpp-0.3.2/tests/unit/test_spec_doc_parser.py +124 -0
  181. doc3gpp-0.3.2/tests/unit/test_spec_doc_search_facade.py +324 -0
  182. doc3gpp-0.3.2/tests/unit/test_spec_doc_service_reads.py +135 -0
  183. doc3gpp-0.3.2/tests/unit/test_spec_doc_settings.py +75 -0
  184. doc3gpp-0.3.2/tests/unit/test_spec_doc_source.py +95 -0
  185. doc3gpp-0.3.2/tests/unit/test_spec_doc_vector_metadata.py +216 -0
  186. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_model.py +12 -1
  187. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_service.py +94 -0
  188. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_sync_hub_page.py +8 -2
  189. doc3gpp-0.3.2/tests/unit/test_tdoc_search_facade.py +259 -0
  190. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_testcase_db_url.py +8 -0
  191. doc3gpp-0.3.2/tests/unit/test_unified_search_models.py +249 -0
  192. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_app.py +25 -9
  193. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_errors.py +29 -5
  194. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_jobs_routes.py +29 -5
  195. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_routes.py +1570 -258
  196. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/web/test_landing_version.py +13 -0
  197. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/web/test_mcp_server.py +89 -0
  198. doc3gpp-0.3.2/tests/unit/web/test_mcp_stdio.py +224 -0
  199. doc3gpp-0.2.1/scripts/dev_run.sh +0 -12
  200. doc3gpp-0.2.1/src/doc3gpp/services/embedding/__init__.py +0 -10
  201. doc3gpp-0.2.1/src/doc3gpp/services/embedding/embedder.py +0 -76
  202. doc3gpp-0.2.1/src/doc3gpp/services/factory.py +0 -376
  203. doc3gpp-0.2.1/src/doc3gpp/web/routes/search.py +0 -272
  204. doc3gpp-0.2.1/tests/integration/test_sqlite_backend.py +0 -32
  205. doc3gpp-0.2.1/tests/unit/test_cli_search.py +0 -509
  206. doc3gpp-0.2.1/tests/unit/test_cli_search_sem.py +0 -82
  207. doc3gpp-0.2.1/tests/unit/test_embedder.py +0 -104
  208. doc3gpp-0.2.1/tests/unit/test_factory_semantic.py +0 -44
  209. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/.env.example +0 -0
  210. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/.github/workflows/publish.yml +0 -0
  211. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/.gitignore +0 -0
  212. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/LICENSE +0 -0
  213. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/doc3gpp.toml.example +0 -0
  214. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/3gpp-knowledge.md +0 -0
  215. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/known-constraints.md +0 -0
  216. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-28-compact-output.md +0 -0
  217. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-28-tdoc-size-limit.md +0 -0
  218. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-29-fts5-search.md +0 -0
  219. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-29-tdoc-cr-body-changes.md +0 -0
  220. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-30-fts5-perf.md +0 -0
  221. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-07-31-embedding-search.md +0 -0
  222. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-01-fts5-hit-rename.md +0 -0
  223. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-01-fts5-semantic-rerank.md +0 -0
  224. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-01-semantic-search-revision.md +0 -0
  225. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-02-all-extra.md +0 -0
  226. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-02-remove-mysql-postgres.md +0 -0
  227. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-02-web-and-mcp-server.md +0 -0
  228. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-03-meeting-sync-display.md +0 -0
  229. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-03-meetings-tdoc-filter.md +0 -0
  230. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-04-web-ui-enhancements.md +0 -0
  231. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-05-tdoc-columns-dropdown.md +0 -0
  232. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-05-web-parse-and-search.md +0 -0
  233. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-07-mcp-sse-transport.md +0 -0
  234. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-10-spec-sync-list-show.md +0 -0
  235. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-11-spec-rapporteurs-comment.md +0 -0
  236. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-11-spec-rapporteurs-filter.md +0 -0
  237. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-12-mcp-spec-sync.md +0 -0
  238. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-12-single-spec-sync.md +0 -0
  239. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-12-spec-show-version-limit.md +0 -0
  240. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-12-spec-sync-dynareport-fetch.md +0 -0
  241. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-idempotent-cancel.md +0 -0
  242. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-mcp-parse-tdoc-url.md +0 -0
  243. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-per-spec-skip-rule.md +0 -0
  244. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-spec-per-version-details-flag.md +0 -0
  245. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-web-job-detail-params.md +0 -0
  246. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-13-web-mcp-meeting-name-filter.md +0 -0
  247. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-14-cover-page-summary-of-change.md +0 -0
  248. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-14-job-progress.md +0 -0
  249. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-14-sync-hub-page.md +0 -0
  250. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-14-version-display.md +0 -0
  251. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-14-web-tdoc-extracted-changes.md +0 -0
  252. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-19-tdocs-xlsx-metadata.md +0 -0
  253. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-08-19-web-mcp-tdoc-show-by-url.md +0 -0
  254. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-09-11-ran5-testcases.md +0 -0
  255. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-09-12-testcase-nested-statuses.md +0 -0
  256. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-09-12-testcase-separate-db.md +0 -0
  257. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/plans/2026-09-13-resource-schema.md +0 -0
  258. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-28-compact-output-design.md +0 -0
  259. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-28-tdoc-size-limit-design.md +0 -0
  260. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-29-fts5-search-design.md +0 -0
  261. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-29-tdoc-cr-body-changes-design.md +0 -0
  262. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-30-fts5-perf.md +0 -0
  263. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-07-31-embedding-search-design.md +0 -0
  264. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-01-fts5-hit-rename-design.md +0 -0
  265. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-01-fts5-semantic-rerank-design.md +0 -0
  266. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-01-semantic-search-revision-design.md +0 -0
  267. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-02-all-extra-design.md +0 -0
  268. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-02-remove-mysql-postgres-design.md +0 -0
  269. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-02-web-and-mcp-server-design.md +0 -0
  270. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-03-meeting-sync-display-design.md +0 -0
  271. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-03-meetings-tdoc-filter-design.md +0 -0
  272. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-04-web-ui-enhancements-design.md +0 -0
  273. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-05-tdoc-columns-dropdown-design.md +0 -0
  274. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-05-web-parse-and-search-design.md +0 -0
  275. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-10-spec-sync-list-show-design.md +0 -0
  276. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-11-spec-rapporteurs-comment-design.md +0 -0
  277. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-11-spec-rapporteurs-filter-design.md +0 -0
  278. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-12-mcp-spec-sync-design.md +0 -0
  279. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-12-single-spec-sync-design.md +0 -0
  280. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-12-spec-show-version-limit-design.md +0 -0
  281. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-12-spec-sync-dynareport-fetch-design.md +0 -0
  282. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-docs-review-design.md +0 -0
  283. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-idempotent-cancel-design.md +0 -0
  284. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-mcp-parse-tdoc-url-design.md +0 -0
  285. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-spec-per-version-details-flag-design.md +0 -0
  286. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-web-job-detail-params-design.md +0 -0
  287. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-13-web-mcp-meeting-name-filter-design.md +0 -0
  288. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-14-cover-page-summary-of-change-design.md +0 -0
  289. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-14-sync-hub-page-design.md +0 -0
  290. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-14-version-display-design.md +0 -0
  291. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-14-web-jobs-cancel-button-design.md +0 -0
  292. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-14-web-tdoc-extracted-changes-design.md +0 -0
  293. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-19-tdocs-xlsx-metadata-design.md +0 -0
  294. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-08-19-web-mcp-tdoc-show-by-url-design.md +0 -0
  295. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-09-11-ran5-testcases-design.md +0 -0
  296. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-09-12-testcase-nested-statuses-design.md +0 -0
  297. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-09-12-testcase-separate-db-design.md +0 -0
  298. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/docs/superpowers/specs/2026-09-13-resource-schema-design.md +0 -0
  299. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/scripts/test_sqlite.sh +0 -0
  300. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/cli_auto_sync.py +0 -0
  301. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/cli_filters.py +0 -0
  302. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/cli_url_helpers.py +0 -0
  303. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/config.py +0 -0
  304. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/__init__.py +0 -0
  305. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/meeting.py +0 -0
  306. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/sync.py +0 -0
  307. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tdoc_cr.py +0 -0
  308. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tdoc_cr_change_details.py +0 -0
  309. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tdoc_file.py +0 -0
  310. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tdoc_show.py +0 -0
  311. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/testcase.py +0 -0
  312. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/tsg.py +0 -0
  313. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/models/wi.py +0 -0
  314. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/__init__.py +0 -0
  315. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/calendar_parser.py +0 -0
  316. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/__init__.py +0 -0
  317. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/body_changes.py +0 -0
  318. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/cover_page.py +0 -0
  319. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/cr_parsers.py +0 -0
  320. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/header.py +0 -0
  321. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/helpers.py +0 -0
  322. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/ttcn_functions.py +0 -0
  323. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr/ttcn_sections.py +0 -0
  324. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/cr_parser.py +0 -0
  325. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/direct_extractor.py +0 -0
  326. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/html_parsers.py +0 -0
  327. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/normalizers.py +0 -0
  328. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/spec_parser.py +0 -0
  329. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/spec_release.py +0 -0
  330. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/tdoc_file_parser.py +0 -0
  331. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/tdoc_parser.py +0 -0
  332. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/tdoc_parsers.py +0 -0
  333. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/testcase_parser.py +0 -0
  334. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/parsers/wi_parser.py +0 -0
  335. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/repository/__init__.py +0 -0
  336. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/__init__.py +0 -0
  337. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/cache.py +0 -0
  338. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/cache_keys.py +0 -0
  339. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/calendar_source.py +0 -0
  340. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/client.py +0 -0
  341. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/ftp_source.py +0 -0
  342. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/portal_source.py +0 -0
  343. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/spec_source.py +0 -0
  344. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/tdoc_zip_source.py +0 -0
  345. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/testcase_source.py +0 -0
  346. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/scraping/wi_source.py +0 -0
  347. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/__init__.py +0 -0
  348. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/_duration.py +0 -0
  349. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/meetings_service.py +0 -0
  350. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/tdoc_cr_service.py +0 -0
  351. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/tdoc_file_service.py +0 -0
  352. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/tdoc_service.py +0 -0
  353. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/tdoc_sync_coordinator.py +0 -0
  354. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/testcase_service.py +0 -0
  355. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/tsg_service.py +0 -0
  356. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/services/wi_service.py +0 -0
  357. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/settings/__init__.py +0 -0
  358. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/settings/config_source.py +0 -0
  359. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/settings/loader.py +0 -0
  360. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/__init__.py +0 -0
  361. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/backends/__init__.py +0 -0
  362. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/cache.py +0 -0
  363. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/compression.py +0 -0
  364. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/__init__.py +0 -0
  365. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/base.py +0 -0
  366. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/fts5_query.py +0 -0
  367. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/migrations/README.md +0 -0
  368. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/db/testcase_base.py +0 -0
  369. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/export.py +0 -0
  370. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/__init__.py +0 -0
  371. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/meeting_sql.py +0 -0
  372. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/rich_filters.py +0 -0
  373. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tdoc_cr_change_details_sql.py +0 -0
  374. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tdoc_cr_sql.py +0 -0
  375. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tdoc_cr_ttcn_sql.py +0 -0
  376. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tdoc_file_sql.py +0 -0
  377. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/testcase_sql.py +0 -0
  378. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/tsg_sql.py +0 -0
  379. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/storage/repositories/wi_sql.py +0 -0
  380. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/__init__.py +0 -0
  381. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/filters.py +0 -0
  382. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/install.py +0 -0
  383. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/meetings.py +0 -0
  384. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/sync.py +0 -0
  385. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/tdocs.py +0 -0
  386. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/testcases.py +0 -0
  387. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/tsgs.py +0 -0
  388. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/routes/wis.py +0 -0
  389. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/htmx.min.js +0 -0
  390. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/job_poller.js +0 -0
  391. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/meeting_sync.js +0 -0
  392. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/search.js +0 -0
  393. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/spec_clipboard.js +0 -0
  394. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/spec_sync.js +0 -0
  395. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/tdoc_columns.js +0 -0
  396. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/static/js/tdoc_parse.js +0 -0
  397. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/job_status.html +0 -0
  398. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/landing.html +0 -0
  399. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/meeting_list.html +0 -0
  400. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/meeting_show.html +0 -0
  401. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/_job_row.html +0 -0
  402. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/job_status.html +0 -0
  403. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/meeting_filters.html +0 -0
  404. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/meeting_results.html +0 -0
  405. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/pagination.html +0 -0
  406. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/schema_results.html +0 -0
  407. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/sync_recent_jobs.html +0 -0
  408. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/tdoc_filters.html +0 -0
  409. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/tdoc_results.html +0 -0
  410. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/testcase_filters.html +0 -0
  411. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/testcase_results.html +0 -0
  412. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/wi_filters.html +0 -0
  413. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/partials/wi_results.html +0 -0
  414. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/schema.html +0 -0
  415. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/spec_list.html +0 -0
  416. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/tdoc_content.html +0 -0
  417. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/tdoc_list.html +0 -0
  418. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/tdoc_show.html +0 -0
  419. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/testcase_list.html +0 -0
  420. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/testcase_show.html +0 -0
  421. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/tsg_list.html +0 -0
  422. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/tsg_show.html +0 -0
  423. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates/wi_list.html +0 -0
  424. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/templates_setup.py +0 -0
  425. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/src/doc3gpp/web/workers/__init__.py +0 -0
  426. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/sample_pages/3GPP-meeting-R5.html +0 -0
  427. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/search_corpus.py +0 -0
  428. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/spec_pages/R5_crs.html +0 -0
  429. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/spec_pages/R5_detail.html +0 -0
  430. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/spec_pages/R5_detail_portal.html +0 -0
  431. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/spec_pages/R5_etsi.html +0 -0
  432. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/spec_pages/R5_list.html +0 -0
  433. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/C6-250028.zip +0 -0
  434. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5-227476.zip +0 -0
  435. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5-253079.zip +0 -0
  436. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5s260009.zip +0 -0
  437. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5s260051.zip +0 -0
  438. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5s260135.zip +0 -0
  439. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_cr_doc/R5s260176.zip +0 -0
  440. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_xlsx/TDoc_List_Meeting_85434_portal.xlsx +0 -0
  441. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/tdoc_xlsx/TDoc_List_Meeting_RAN5#111.xlsx +0 -0
  442. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/fixtures/wi_pages/R5.html +0 -0
  443. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_auto_sync_sqlite.py +0 -0
  444. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_cli_sqlite.py +0 -0
  445. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_config_set_cli_sqlite.py +0 -0
  446. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_db_reset_sqlite.py +0 -0
  447. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_embed_after_parse.py +0 -0
  448. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_meeting_service_sqlite.py +0 -0
  449. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_migrate_tsg_spec_last_sync_drop.py +0 -0
  450. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_online_3gpp_calendar.py +0 -0
  451. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_online_spec_sync.py +0 -0
  452. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_online_tdoc_fetch_r5.py +0 -0
  453. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_online_tdoc_parse.py +0 -0
  454. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_online_testcase_sync.py +0 -0
  455. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_parse_tdoc_url_job_sqlite.py +0 -0
  456. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_schema_parity.py +0 -0
  457. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_sdk_integration.py +0 -0
  458. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_after_parse.py +0 -0
  459. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_extras_disabled.py +0 -0
  460. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_index_lifecycle.py +0 -0
  461. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_indexes.py +0 -0
  462. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_schema.py +0 -0
  463. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_snippet_column.py +0 -0
  464. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_search_weighted_bm25.py +0 -0
  465. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_semantic_extras_disabled.py +0 -0
  466. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_spec_migration.py +0 -0
  467. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_cr_change_details_sqlite.py +0 -0
  468. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_cr_rename_migration.py +0 -0
  469. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_cr_sqlite.py +0 -0
  470. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_cr_ttcn_sqlite.py +0 -0
  471. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_file_sqlite.py +0 -0
  472. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_parse_direct_sqlite.py +0 -0
  473. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_parse_ftp_batch_sqlite.py +0 -0
  474. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdoc_parse_local_batch_sqlite.py +0 -0
  475. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdocs_xlsx_metadata_migration_sqlite.py +0 -0
  476. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tdocs_xlsx_metadata_sqlite.py +0 -0
  477. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_testcase_cli.py +0 -0
  478. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_testcase_sql.py +0 -0
  479. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_tsg_sqlite.py +0 -0
  480. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_vector_schema_migration.py +0 -0
  481. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_web_end_to_end.py +0 -0
  482. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/integration/test_wi_sqlite.py +0 -0
  483. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/_job_polling_smoke.js +0 -0
  484. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_bind_job_polling_on_terminal.py +0 -0
  485. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_body_changes_extractor.py +0 -0
  486. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cache_keys.py +0 -0
  487. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_calendar_parser.py +0 -0
  488. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_calendar_parser_defensive.py +0 -0
  489. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cli_auto_sync.py +0 -0
  490. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cli_filters.py +0 -0
  491. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_cli_version.py +0 -0
  492. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_compact_helpers.py +0 -0
  493. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_config_init_cli.py +0 -0
  494. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_config_set_cli.py +0 -0
  495. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_config_writer.py +0 -0
  496. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_docx_converter.py +0 -0
  497. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_ftp_listing.py +0 -0
  498. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_fts5_query.py +0 -0
  499. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_job_row_partial.py +0 -0
  500. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_list_output_format.py +0 -0
  501. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_cli.py +0 -0
  502. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_cli_filters_combined.py +0 -0
  503. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_cli_invalid_fields.py +0 -0
  504. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_cli_location_filter.py +0 -0
  505. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_repository_combined_filters.py +0 -0
  506. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_repository_filters.py +0 -0
  507. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_repository_location_filter.py +0 -0
  508. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_meeting_repository_upsert.py +0 -0
  509. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_parse_tdoc_url_route.py +0 -0
  510. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_parsers_utils.py +0 -0
  511. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_portal_source.py +0 -0
  512. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_protocols_semantic.py +0 -0
  513. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_rrf.py +0 -0
  514. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_scraper_client.py +0 -0
  515. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_search_query_builder.py +0 -0
  516. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_search_settings.py +0 -0
  517. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_semantic_models.py +0 -0
  518. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_semantic_reranker.py +0 -0
  519. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_orm.py +0 -0
  520. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_parser.py +0 -0
  521. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_release.py +0 -0
  522. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_spec_source.py +0 -0
  523. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_storage_utils.py +0 -0
  524. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cache.py +0 -0
  525. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cli_fields.py +0 -0
  526. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cr_change_details_model.py +0 -0
  527. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cr_model.py +0 -0
  528. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cr_service.py +0 -0
  529. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cr_service_body_changes.py +0 -0
  530. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_cr_service_ftp_batch.py +0 -0
  531. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_file_parser.py +0 -0
  532. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_file_service.py +0 -0
  533. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_file_source.py +0 -0
  534. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_parse_cli.py +0 -0
  535. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_parse_direct.py +0 -0
  536. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_parse_settings.py +0 -0
  537. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_parse_url_batch.py +0 -0
  538. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_parser.py +0 -0
  539. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_repository_crud.py +0 -0
  540. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_repository_filters.py +0 -0
  541. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_service_sync.py +0 -0
  542. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_show_record.py +0 -0
  543. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_sync_cli.py +0 -0
  544. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_sync_coordinator.py +0 -0
  545. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_url_not_found.py +0 -0
  546. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tdoc_zip_source.py +0 -0
  547. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_testcase_model.py +0 -0
  548. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_testcase_parser.py +0 -0
  549. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_testcase_service.py +0 -0
  550. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_testcase_source.py +0 -0
  551. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tsg_cli.py +0 -0
  552. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tsg_repository.py +0 -0
  553. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tsg_service.py +0 -0
  554. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_tsg_url_pattern.py +0 -0
  555. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_ttcn_functions.py +0 -0
  556. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_filters.py +0 -0
  557. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_install.py +0 -0
  558. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_web_template_filters.py +0 -0
  559. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_wi_cli.py +0 -0
  560. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_wi_parser.py +0 -0
  561. {doc3gpp-0.2.1 → doc3gpp-0.3.2}/tests/unit/test_wi_repository_filters.py +0 -0
@@ -0,0 +1,2 @@
1
+ *
2
+ !.gitignore
@@ -0,0 +1,179 @@
1
+ # Final Review Fix Report
2
+
3
+ ## Status
4
+
5
+ Implemented and committed as `c37f292` (`fix(spec-doc): close final metadata review gaps`).
6
+
7
+ The approved untracked implementation plan,
8
+ `docs/superpowers/plans/2026-09-24-spec-doc-metadata-and-portal-fix.md`, was not
9
+ modified or staged. Pre-existing worktree changes outside this final fix wave
10
+ were also left untouched.
11
+
12
+ ## Findings Addressed
13
+
14
+ ### FTS5 nullable metadata
15
+
16
+ `SQLAlchemySpecDocSearchRepository.upsert_for_version()` now preserves
17
+ `None` for nullable `sections` and `tables` instead of converting them to empty
18
+ strings. FTS5 `null` and `not-null` predicates therefore match the relational
19
+ chunk contract.
20
+
21
+ Added explicit integration coverage for both fields and all related rich-filter
22
+ branches:
23
+
24
+ - `null`
25
+ - `not-null`
26
+ - positive LIKE
27
+ - negated `!pattern`
28
+ - simultaneous `sections` and `tables` filters with AND semantics
29
+
30
+ ### Overlap metadata scope
31
+
32
+ `chunk_blocks()` now tracks metadata at source-token granularity. When overlap
33
+ tokens are prepended, only metadata attached to the trailing token range is
34
+ merged into the following chunk. Ordered deduplication and current-chunk
35
+ metadata remain unchanged.
36
+
37
+ Regression coverage includes:
38
+
39
+ - a previous chunk with earlier and later section metadata where only the later
40
+ section overlaps;
41
+ - the equivalent table-overlap case;
42
+ - repeated section/table metadata deduplication.
43
+
44
+ Existing atomic-table, chunk-boundary, character-ceiling, file-tag, and empty
45
+ metadata behavior remains covered.
46
+
47
+ ### Stable stale-only rebuild cutoff
48
+
49
+ `rebuild_batch(stale_only=True)` captures `last_indexed_parsed_at` once before
50
+ iterating batches and binds that stable cutoff for every page. Per-version
51
+ `upsert_for_version()` watermark updates can no longer remove older stale rows
52
+ from later pages.
53
+
54
+ The regression seeds two stale versions and rebuilds with `batch_size=1`; both
55
+ versions must be indexed.
56
+
57
+ ### Configured cache path expansion
58
+
59
+ `SpecDocSettings.cache_dir` now applies `Path.expanduser()` after Pydantic
60
+ validation. TOML-style `~/.cache/doc3gpp/specs` values resolve under the user
61
+ home, while absolute explicit paths and the absolute default remain unchanged.
62
+
63
+ ### Contract coverage
64
+
65
+ The final wave pins:
66
+
67
+ - exact `_SPEC_DOC_SNIPPET_COLUMNS` ordering;
68
+ - removal of all split chunk/hit/filter DTO fields;
69
+ - nullable FTS metadata behavior;
70
+ - complete rich-filter semantics for both combined metadata fields;
71
+ - overlap deduplication and table overlap;
72
+ - configured cache path behavior.
73
+
74
+ ### Vector-side `release` semantics
75
+
76
+ The existing semantic implementation intentionally uses exact equality for
77
+ vector-side `spec_id`, `version`, and `release`, while vector-side `sections`
78
+ and `tables` use plain LIKE. The FTS side remains the rich-filter path.
79
+
80
+ This is now explicit and consistent in:
81
+
82
+ - `src/doc3gpp/storage/repositories/spec_doc_vector_sql.py`;
83
+ - `src/doc3gpp/services/spec_doc_semantic_service.py`;
84
+ - `docs/architecture.md`;
85
+ - `docs/cli.md`;
86
+ - `AGENTS.md`.
87
+
88
+ An optional sqlite-vec regression asserts that `release="Rel-18"` matches and
89
+ `release="Rel-1%"` does not, preserving the intentional exact contract.
90
+
91
+ ## TDD Evidence
92
+
93
+ The new regression tests were written before production changes.
94
+
95
+ Initial red run:
96
+
97
+ ```text
98
+ rtk pytest tests/unit/test_spec_doc_models.py tests/unit/test_spec_doc_settings.py tests/unit/test_spec_doc_chunker.py tests/integration/test_spec_doc_search_repo.py -q
99
+ Pytest: 33 passed, 7 failed
100
+ ```
101
+
102
+ The failures were the expected reviewer defects:
103
+
104
+ - configured `~` cache path stayed literal;
105
+ - section overlap copied the earlier metadata;
106
+ - table overlap copied the earlier metadata;
107
+ - nullable FTS filters returned no matching rows;
108
+ - stale-only batch size 1 indexed only one of two stale versions.
109
+
110
+ Green focused run after the minimal fixes:
111
+
112
+ ```text
113
+ rtk pytest tests/unit/test_spec_doc_models.py tests/unit/test_spec_doc_settings.py tests/unit/test_spec_doc_chunker.py tests/integration/test_spec_doc_search_repo.py -q
114
+ 40 passed
115
+ ```
116
+
117
+ The covering spec-document/web/MCP run then passed:
118
+
119
+ ```text
120
+ rtk pytest tests/unit/test_spec_doc_*.py tests/integration/test_spec_doc_*.py tests/unit/test_web_routes.py tests/integration/test_mcp_end_to_end.py -q
121
+ 330 passed
122
+ ```
123
+
124
+ ## Verification
125
+
126
+ Full offline SQLite suite:
127
+
128
+ ```text
129
+ rtk ./scripts/test_sqlite.sh
130
+ 2405 passed, 1 skipped, 109 warnings in 103.45s
131
+ ```
132
+
133
+ The skip is the existing optional-dependency skip. Existing collection and
134
+ datetime deprecation warnings remain; the stale-rebuild path also exercises the
135
+ project's existing `datetime.utcnow()` warning in
136
+ `spec_doc_search_service.py`.
137
+
138
+ Lint:
139
+
140
+ ```text
141
+ rtk ruff check .
142
+ clean, exit 0
143
+ ```
144
+
145
+ Whitespace:
146
+
147
+ ```text
148
+ rtk git diff --check
149
+ clean, exit 0
150
+ ```
151
+
152
+ The focused fix files also passed their targeted Ruff check before the full
153
+ gate.
154
+
155
+ ## Files In Commit
156
+
157
+ - `AGENTS.md`
158
+ - `docs/architecture.md`
159
+ - `docs/cli.md`
160
+ - `src/doc3gpp/parsers/spec_doc_chunker.py`
161
+ - `src/doc3gpp/settings/schema.py`
162
+ - `src/doc3gpp/storage/repositories/spec_doc_search_sql.py`
163
+ - `tests/integration/test_spec_doc_search_repo.py`
164
+ - `tests/unit/test_spec_doc_chunker.py`
165
+ - `tests/unit/test_spec_doc_models.py`
166
+ - `tests/unit/test_spec_doc_settings.py`
167
+
168
+ No migration, public repair command, unrelated TDoc behavior, or generated
169
+ artifact was added.
170
+
171
+ ## Concerns
172
+
173
+ - Vector-side semantic behavior was not changed from exact `release` matching;
174
+ the docs now state that contract instead of claiming release LIKE behavior.
175
+ - sqlite-vec-specific assertions are skipped when the optional extension is not
176
+ installed; the core FTS, chunker, cache, and stale-rebuild coverage is
177
+ extension-independent.
178
+ - The repository retains its pre-existing warning set, including UTC datetime
179
+ deprecations.
@@ -0,0 +1,129 @@
1
+ # Task 2 Report
2
+
3
+ ## Status
4
+
5
+ DONE_WITH_CONCERNS
6
+
7
+ ## Files Changed
8
+
9
+ - `src/doc3gpp/parsers/docx_converter.py`
10
+ - Recognizes alphanumeric section identifiers such as `7.2A.3` and `7.2A.3A`.
11
+ - Recognizes table captions with 3GPP identifiers and colon, dash, or whitespace separators.
12
+ - Collapses caption whitespace while retaining caption paragraphs in the block stream.
13
+ - `src/doc3gpp/parsers/spec_doc.py`
14
+ - Adds a natural section sort key that compares numeric tokens numerically and alphabetic tokens case-insensitively.
15
+ - Preserves front-matter and unnumbered-file ordering rules.
16
+ - `tests/unit/test_spec_doc_blocks.py`
17
+ - Adds real in-memory `python-docx` tests for alphanumeric headings and table captions.
18
+ - `tests/unit/test_spec_doc_parser.py`
19
+ - Adds alphanumeric file-ordering and TOC preservation tests.
20
+
21
+ No chunker, ORM, search, web, or unrelated files were modified. `HeadingBlock.section_no`, `TableBlock.table_no/table_title`, and TOC split fields remain unchanged.
22
+
23
+ ## TDD Verification
24
+
25
+ ### Red
26
+
27
+ Command:
28
+
29
+ ```bash
30
+ rtk pytest tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py -v
31
+ ```
32
+
33
+ Result: `10 passed, 3 failed`.
34
+
35
+ The three expected failures were:
36
+
37
+ - `test_heading_accepts_alphanumeric_section_suffixes`: the numeric-only section regex returned `None`.
38
+ - `test_table_caption_accepts_3gpp_identifier_and_separator`: the numeric-only caption regex returned no table number.
39
+ - `test_order_numbered_files_handles_alphanumeric_sections`: the numeric-only `_first_section` path could not order the alphanumeric section.
40
+
41
+ ### Green
42
+
43
+ Command:
44
+
45
+ ```bash
46
+ rtk pytest tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py -v
47
+ ```
48
+
49
+ Result: `13 passed`.
50
+
51
+ Additional checks:
52
+
53
+ - `rtk ruff check src/doc3gpp/parsers/docx_converter.py src/doc3gpp/parsers/spec_doc.py tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py`: no findings.
54
+ - `rtk git diff HEAD^ HEAD --check`: clean.
55
+
56
+ The broader command `rtk pytest tests/unit/test_spec_doc_*.py -v` reports `34 passed, 5 failed`. The five failures are existing Task 3 chunker failures caused by the Task 1 `ChunkDraft` contract change before the chunker has been updated; they are outside this task and were not changed.
57
+
58
+ ## Commit
59
+
60
+ - Hash: `b00a2eb`
61
+ - Message: `fix(spec-doc): recognize alphanumeric sections and tables`
62
+
63
+ ## Self-Review Findings
64
+
65
+ - No Task 2 defects found in the focused review.
66
+ - The heading regex requires an identifier to start with a digit, permits alphanumeric dotted components, and still requires following whitespace.
67
+ - Caption parsing supports the requested identifier and separator forms, normalizes whitespace, and leaves caption paragraphs as `ParagraphBlock` entries.
68
+ - Natural sorting uses token types that are safe to compare in Python tuple ordering and keeps numeric section ordering natural (`7.2` before `7.10`).
69
+ - Existing numeric-section, front-matter, unnumbered-file, and TOC tests remain green.
70
+ - The commit contains only the four files specified by the Task 2 brief.
71
+
72
+ ## Concerns
73
+
74
+ - The full spec-document unit-test glob is not green until the planned Task 3 chunker implementation updates its constructors and metadata handling for the Task 1 DTO contract. This was intentionally left untouched to preserve Task 2 scope.
75
+ - The approved plan file `docs/superpowers/plans/2026-09-24-spec-doc-metadata-and-portal-fix.md` remains pre-existing and untracked; it was not added to the Task 2 commit.
76
+
77
+ ## Fix Round: Alphanumeric Hyphenated Table Suffixes
78
+
79
+ ### Finding Addressed
80
+
81
+ The table-caption identifier grammar previously allowed only numeric suffixes after
82
+ the hyphen. It split identifiers such as `4.4.2-1A` and `4.6.1-4.0A` before the
83
+ suffix. The grammar now permits alphanumeric and dotted components after the
84
+ hyphen, while retaining the existing base identifier rules.
85
+
86
+ The real in-memory DOCX regression coverage now parameterizes colon, dash, and
87
+ whitespace separators for table captions, covers both reviewed identifiers, and
88
+ asserts that the caption remains a `ParagraphBlock` in the block stream.
89
+
90
+ ### TDD Verification
91
+
92
+ Red command:
93
+
94
+ ```bash
95
+ rtk pytest tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py -v
96
+ ```
97
+
98
+ Result: `13 passed, 2 failed`. The two new hyphenated-suffix cases failed with
99
+ the old numeric-only suffix grammar; for example, `4.4.2-1A` was parsed as
100
+ `4.4.2`.
101
+
102
+ Green command:
103
+
104
+ ```bash
105
+ rtk pytest tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py -v
106
+ ```
107
+
108
+ Result: `15 passed`.
109
+
110
+ Targeted lint:
111
+
112
+ ```bash
113
+ rtk ruff check src/doc3gpp/parsers/docx_converter.py src/doc3gpp/parsers/spec_doc.py tests/unit/test_spec_doc_blocks.py tests/unit/test_spec_doc_parser.py
114
+ ```
115
+
116
+ Result: no findings.
117
+
118
+ ### Fix Commit
119
+
120
+ - Hash: `1836c50`
121
+ - Message: `fix(spec-doc): accept alphanumeric table suffixes`
122
+
123
+ ### Remaining Concerns
124
+
125
+ - The broader `rtk pytest tests/unit/test_spec_doc_*.py -v` scope still has the
126
+ previously recorded five Task 3 chunker failures caused by the Task 1 DTO
127
+ contract; no unrelated chunker changes were made in this fix round.
128
+ - The pre-existing untracked plan file remains untracked and was not included in
129
+ either fix commit.
@@ -0,0 +1,255 @@
1
+ # Final Review Fix Report
2
+
3
+ ## Context
4
+
5
+ This fix wave addresses the final review findings for the spec-document web
6
+ portal branch at `9e44230`. The pre-existing untracked approved plan,
7
+ `docs/superpowers/plans/2026-09-24-spec-doc-web-portal.md`, was not modified or
8
+ staged.
9
+
10
+ ## Files Changed
11
+
12
+ - `src/doc3gpp/storage/repositories/spec_doc_sql.py`
13
+ - Removed the `parsed_at` and `chunk_count` success-state mutation from
14
+ `replace_chunks()`.
15
+ - `record_parsed()` is now the only repository operation that marks a source
16
+ parsed or records its final chunk count.
17
+ - `tests/integration/test_spec_doc_service.py`
18
+ - Added a regression test that fails the markdown-cache write after chunks
19
+ are stored, verifies `parsed_at` remains unset, and verifies a subsequent
20
+ non-force parse succeeds rather than being skipped.
21
+ - `tests/integration/test_spec_doc_repo.py`
22
+ - Updated the repository round-trip to assert that chunk replacement alone
23
+ leaves the source unparsed, then explicitly records the successful parse.
24
+ - Added coverage that direct chunk replacement still creates an explicitly
25
+ unparsed source row when no source row exists.
26
+ - `src/doc3gpp/web/templates/spec_doc_show.html`
27
+ - Hides the force checkbox unless the source is parsed.
28
+ - Adds an explicit parsed-state data attribute for defensive client logic.
29
+ - `src/doc3gpp/web/static/js/spec_doc_parse.js`
30
+ - Forces the submitted `force` value to `false` unless the form declares a
31
+ parsed source, even if a stale or injected checkbox is present.
32
+ - `src/doc3gpp/web/templates/partials/spec_doc_show_results.html`
33
+ - Renders the stored TOC file summary, including source filename, file order,
34
+ and first section.
35
+ - `src/doc3gpp/web/templates/partials/spec_doc_chunks.html`
36
+ - Distinguishes a parsed zero-chunk source from a non-matching section
37
+ filter.
38
+ - `tests/unit/test_web_routes.py`
39
+ - Covers force-control availability for unparsed and parsed states, the TOC
40
+ file summary, the zero-chunk message, and the JS parsed-state guard.
41
+ - `docs/web-server.md`
42
+ - Clarifies that the endpoint accepts optional `release`, while the version
43
+ page form submits `spec_ids`, the selected exact `version`, and `force`
44
+ without a release selector.
45
+
46
+ ## Tests And Commands
47
+
48
+ - `rtk pytest tests/integration/test_spec_doc_service.py -k post_chunk_cache_failure -q`
49
+ - Initial TDD red run: failed because `replace_chunks()` had already set
50
+ `parsed_at`; this confirmed the regression exercised the reported bug.
51
+ - `rtk pytest tests/integration/test_spec_doc_service.py tests/integration/test_spec_doc_repo.py -q`
52
+ - `10 passed`.
53
+ - `rtk pytest tests/unit/test_web_routes.py -k 'spec_doc_show or spec_doc_parse_js' -q`
54
+ - `8 passed`.
55
+ - `rtk pytest tests/unit/test_spec_doc_service_reads.py tests/unit/test_spec_doc_source.py tests/integration/test_spec_doc_service.py tests/integration/test_spec_doc_repo.py tests/integration/test_spec_doc_search_repo.py tests/integration/test_spec_doc_search_service.py tests/integration/test_spec_doc_web.py tests/unit/test_web_routes.py tests/unit/web/test_landing_version.py -q`
56
+ - `225 passed`.
57
+ - `rtk pytest tests/integration/test_spec_doc_cli.py tests/unit/test_spec_doc_settings.py tests/unit/test_spec_doc_models.py tests/unit/test_spec_doc_parser.py tests/unit/test_spec_doc_chunker.py -q`
58
+ - `23 passed`.
59
+ - `rtk ./scripts/test_sqlite.sh`
60
+ - `2356 passed, 1 skipped, 108 warnings`.
61
+ - Warnings are the repository's existing pytest collection and deprecation
62
+ warnings; no test failures occurred.
63
+ - `rtk ruff check .`
64
+ - Clean.
65
+ - `rtk git diff --check`
66
+ - Clean.
67
+
68
+ ## Self-Review
69
+
70
+ - A failed parse after chunk replacement and before markdown-cache completion
71
+ no longer creates a false successful parse marker. The retry path uses the
72
+ existing ZIP cache and reaches `record_parsed()` normally.
73
+ - Existing force re-parse behavior remains available for parsed sources. The
74
+ browser checkbox is absent for unparsed/downloaded sources, and the client
75
+ independently clamps `force` to `false` in that state.
76
+ - The version page's TOC now includes the complete stored file summary using
77
+ the same fields as the existing standalone TOC page.
78
+ - A parsed source with `chunk_count == 0` gets an incomplete/corrupt/zero-chunk
79
+ message. A parsed source with chunks but no rows after filtering retains the
80
+ filter-empty message.
81
+ - The documentation now separates endpoint query support from the form's
82
+ exact-version job payload.
83
+ - No CLI, MCP, JSON, schema, or job contract was changed.
84
+ - No direct semantic nested-hit route test was added; this remains the
85
+ explicitly accepted test-only residual from the prior review.
86
+
87
+ ## Concerns
88
+
89
+ - TOC persistence, chunk replacement, filesystem cache writes, and the parsed
90
+ ledger remain separate operations because the existing repository architecture
91
+ does not provide one cross-storage transaction. A failed attempt can leave
92
+ intermediate TOC/chunk/cache data, but `parsed_at` remains unset and the
93
+ next parse replaces those intermediates before recording success.
94
+ - The full suite retains the existing 108 warnings noted above; they are not
95
+ introduced by this fix wave.
96
+
97
+ ## Fix Round 2
98
+
99
+ ### Finding Addressed
100
+
101
+ A forced re-parse of an already parsed version could leave the old non-null
102
+ `parsed_at` marker in place when post-chunk/cache work failed. A later
103
+ non-force parse then treated the failed re-parse as an immutable success and
104
+ skipped it.
105
+
106
+ ### Files Changed
107
+
108
+ - `src/doc3gpp/storage/repositories/spec_doc_sql.py`
109
+ - `record_download()` now clears `parsed_at` and resets `chunk_count` when
110
+ refreshing an existing source row. This invalidates the previous success
111
+ marker at the force-download boundary while preserving the existing method
112
+ signature and repository flow.
113
+ - `tests/integration/test_spec_doc_service.py`
114
+ - Added coverage that parses a version successfully, forces a re-parse that
115
+ fails during markdown-cache writing, verifies the old marker is cleared,
116
+ and verifies a subsequent non-force parse succeeds.
117
+ - `.superpowers/sdd/2026-09-24-spec-doc-web-portal/final-fix-report.md`
118
+ - Appended this fix-round record. The approved untracked plan remains
119
+ untouched and unstaged.
120
+
121
+ ### Tests And Commands
122
+
123
+ - `rtk pytest tests/integration/test_spec_doc_service.py -k 'failed_force_reparse_invalidates_old_marker_for_retry or post_chunk_cache_failure or force_reparses' -q`
124
+ - `3 passed`.
125
+ - `rtk pytest tests/integration/test_spec_doc_repo.py -q`
126
+ - `2 passed`.
127
+ - `rtk pytest tests/integration/test_spec_doc_service.py tests/integration/test_spec_doc_repo.py tests/integration/test_spec_doc_search_repo.py tests/integration/test_spec_doc_search_service.py tests/integration/test_spec_doc_web.py tests/unit/test_spec_doc_service_reads.py tests/unit/test_web_routes.py tests/unit/web/test_landing_version.py -q`
128
+ - `220 passed`.
129
+ - `rtk ./scripts/test_sqlite.sh`
130
+ - `2357 passed, 1 skipped, 108 warnings`.
131
+ - `rtk ruff check .`
132
+ - Clean.
133
+ - `rtk git diff --check`
134
+ - Clean.
135
+
136
+ ### Self-Review
137
+
138
+ - A successful force re-parse still reaches `record_parsed()` and restores a
139
+ non-null marker with the new chunk count.
140
+ - A non-force immutable skip does not call `record_download()` when the ZIP
141
+ cache and parsed source already exist, so existing skip behavior is
142
+ unchanged.
143
+ - If a forced download or a cache-miss download replaces an existing source,
144
+ its previous success marker is invalidated before parse work begins; any
145
+ later failure therefore remains retryable.
146
+ - `record_parsed()` remains the only operation that marks a source as
147
+ successfully parsed.
148
+ - The fix changes no schema, service signature, CLI, HTTP, MCP, or job
149
+ contract.
150
+
151
+ ### Concerns
152
+
153
+ - As in the first fix round, TOC/chunk/cache writes and the source ledger use
154
+ separate repository/filesystem transactions. A failed force re-parse may
155
+ leave intermediate replacement data, but the source remains unparsed and a
156
+ subsequent retry replaces those intermediates before recording success.
157
+ - The full suite retains the existing 108 warnings; no new warning category
158
+ was introduced by this round.
159
+
160
+ ## Fix Round 3
161
+
162
+ ### Finding Addressed
163
+
164
+ The round-2 placement was still too late for a forced network failure:
165
+ `SpecDocService.fetch(force=True)` called `_fetcher()` before
166
+ `record_download()`, so a failed download left an already parsed source's old
167
+ `parsed_at` marker intact. The final fix invalidates parse state before the
168
+ forced fetch, without recording a download that did not succeed.
169
+
170
+ ### TDD Failing-Test Evidence
171
+
172
+ Added `test_failed_force_download_invalidates_old_marker_for_retry` to
173
+ `tests/integration/test_spec_doc_service.py`. The first focused run was:
174
+
175
+ ```text
176
+ rtk pytest tests/integration/test_spec_doc_service.py -k failed_force_download_invalidates_old_marker_for_retry -q
177
+ Pytest: 0 passed, 1 failed
178
+ AssertionError: source.parsed_at is None
179
+ ```
180
+
181
+ The failure reproduced the confirmed root cause: the source remained parsed
182
+ after the forced `_fetcher()` raised `OSError("upstream unavailable")`.
183
+
184
+ ### Files Changed
185
+
186
+ - `src/doc3gpp/repository/protocols.py`
187
+ - Added the clearly named `SpecDocRepository.invalidate_parse_state()`
188
+ operation.
189
+ - `src/doc3gpp/storage/repositories/spec_doc_sql.py`
190
+ - Implemented `invalidate_parse_state()` as a committed update of only
191
+ `parsed_at` and `chunk_count` for an existing source row.
192
+ - Kept `record_download()` responsible for successful-download metadata;
193
+ it no longer doubles as parse-state invalidation.
194
+ - `src/doc3gpp/services/spec_doc_service.py`
195
+ - On `force=True`, resolves the existing source and invalidates its parse
196
+ state before invoking `_fetcher()`.
197
+ - Does nothing for a missing source, preserving the first-download path.
198
+ - `tests/integration/test_spec_doc_service.py`
199
+ - Added the required already-parsed, forced-network-failure, then
200
+ non-force-retry regression.
201
+ - `tests/integration/test_spec_doc_repo.py`
202
+ - Verifies explicit invalidation clears only parse state while preserving
203
+ release, FTP URL, download timestamp, and DOCX count.
204
+ - `.superpowers/sdd/2026-09-24-spec-doc-web-portal/final-fix-report.md`
205
+ - Appended this round-3 record. The approved untracked plan remains
206
+ untouched and unstaged.
207
+
208
+ ### Tests And Commands
209
+
210
+ - `rtk pytest tests/integration/test_spec_doc_service.py -k failed_force_download_invalidates_old_marker_for_retry -q`
211
+ - Initial TDD red run: `0 passed, 1 failed`, with the expected stale
212
+ `parsed_at` assertion failure.
213
+ - `rtk pytest tests/integration/test_spec_doc_service.py -k 'failed_force_download_invalidates_old_marker_for_retry or failed_force_reparse_invalidates_old_marker_for_retry or post_chunk_cache_failure or force_reparses' -q`
214
+ - `4 passed` after the fix.
215
+ - `rtk pytest tests/integration/test_spec_doc_repo.py -q`
216
+ - `2 passed`.
217
+ - `rtk pytest tests/integration/test_spec_doc_service.py tests/integration/test_spec_doc_repo.py tests/integration/test_spec_doc_search_repo.py tests/integration/test_spec_doc_search_service.py tests/integration/test_spec_doc_web.py tests/unit/test_spec_doc_service_reads.py tests/unit/test_web_routes.py tests/unit/web/test_landing_version.py -q`
218
+ - `221 passed`.
219
+ - `rtk ./scripts/test_sqlite.sh`
220
+ - `2358 passed, 1 skipped, 108 warnings`.
221
+ - `rtk ruff check .`
222
+ - Clean.
223
+ - `rtk git diff --check`
224
+ - Clean.
225
+
226
+ ### Self-Review
227
+
228
+ - A forced re-parse with an existing source clears the success marker before
229
+ any network, ZIP-size, cache-write, or parse operation can fail.
230
+ - The invalidation operation preserves truthful download metadata and does not
231
+ create a source row or claim that a forced download succeeded.
232
+ - Successful force re-parse still runs `record_download()` after bytes arrive,
233
+ then `record_parsed()` after all required parse/cache work completes.
234
+ - A non-force immutable skip does not call the invalidation operation because
235
+ it returns through the existing cache/parsed check without entering the
236
+ forced path.
237
+ - First-parse failures and the prior post-chunk/cache failure regression remain
238
+ covered and retryable.
239
+ - The round-2 reset inside `record_download()` was removed; round 3 replaces
240
+ that late invalidation with the explicit pre-fetch operation requested by the
241
+ review.
242
+ - No web portal behavior, schema, job payload, CLI contract, or public service
243
+ signature changed.
244
+
245
+ ### Concerns
246
+
247
+ - Parse-state invalidation and the later network/cache/parse work remain
248
+ separate transactions under the existing repository architecture. After a
249
+ forced network failure, prior download metadata and cached bytes remain, but
250
+ `parsed_at` is intentionally null so the source is not treated as a
251
+ successful parse and the next non-force run retries.
252
+ - A failure after TOC/chunk replacement can still leave intermediate data; the
253
+ existing retry path replaces it before `record_parsed()` marks success.
254
+ - The full suite retains the existing 108 warnings; no new warning category
255
+ was introduced by this round.
@@ -0,0 +1,62 @@
1
+ # Task 2 Report: Add Spec Document Version Read Page
2
+
3
+ ## Files Changed
4
+
5
+ - `src/doc3gpp/web/routes/spec_docs.py`
6
+ - Added `GET /specs/{spec_id}/docs` before the existing TOC route.
7
+ - Resolves the parent spec and exact requested version through the injected `SpecService`.
8
+ - Reads source, TOC, and chunks only through `SpecDocService.get_source`, `get_toc`, and `list_chunks`.
9
+ - Supports release/section filters, bounded chunk pagination, one-row probe fetching, and HTMX `#results` fragments.
10
+ - Preserves the existing error mapping for missing specs, missing versions, disabled spec-doc services, and invalid query values.
11
+ - `src/doc3gpp/web/templates/spec_doc_show.html`
12
+ - Added the full version document page with spec/version identity, parent-spec link, source links, and metadata.
13
+ - `src/doc3gpp/web/templates/partials/spec_doc_show_results.html`
14
+ - Added the `#results` fragment with source state, parsed metadata, TOC, and chunk composition.
15
+ - `src/doc3gpp/web/templates/partials/spec_doc_chunks.html`
16
+ - Added chunk cards, section/table metadata, source filenames, preformatted text, and filter-preserving pagination.
17
+ - `src/doc3gpp/web/static/style.css`
18
+ - Added responsive source/chunk page styles while reusing existing portal primitives.
19
+ - `tests/unit/test_web_routes.py`
20
+ - Added fake public spec-document service data and focused tests for unparsed state, parsed TOC/chunks, probe pagination, HTMX fragments, and unknown versions.
21
+ - `.superpowers/sdd/2026-09-24-spec-doc-web-portal/task-2-report.md`
22
+ - Added this report.
23
+
24
+ The pre-existing untracked `docs/superpowers/plans/2026-09-24-spec-doc-web-portal.md` was not modified or staged.
25
+
26
+ ## Tests And Commands
27
+
28
+ - `rtk pytest tests/unit/test_web_routes.py -k "spec_doc_show" -q`
29
+ - Initial TDD red run: `0 passed, 5 failed`; the expected failure was HTTP 404 because the new route did not yet exist.
30
+ - `rtk pytest tests/unit/test_web_routes.py -k "spec_doc_show" -q`
31
+ - Final result: `5 passed`.
32
+ - `rtk pytest tests/integration/test_spec_doc_web.py -q`
33
+ - Final result: `3 passed`.
34
+ - `rtk pytest tests/unit/test_web_routes.py -q`
35
+ - Final result: `178 passed`.
36
+ - `rtk ruff check src/doc3gpp/web/routes/spec_docs.py tests/unit/test_web_routes.py`
37
+ - Final result: clean (`[]`).
38
+ - `rtk git diff --check`
39
+ - Final result: clean.
40
+ - `rtk pytest`
41
+ - Collection did not start because three existing integration/unit modules import `tests.integration.test_web_end_to_end` and the plain executable entry point did not expose the repository root as the `tests` package (`3 ModuleNotFoundError` collection errors).
42
+ - `rtk python -m pytest -q`
43
+ - Final result: `2346 passed, 1 skipped, 10 deselected, 18 warnings` in `401.75s`.
44
+ - `rtk grep '_doc_repo|fetch|parse form|spec-doc-parse-form|jobs/parse' src/doc3gpp/web/routes/spec_docs.py`
45
+ - Final result: no route/private-repository/fetch/parse-control matches.
46
+
47
+ ## Self-Review
48
+
49
+ - The route is registered before `/specs/{spec_id}/docs/toc`, so the static TOC path remains reachable.
50
+ - Exact version identity is verified after `SpecService.list_versions(..., version=version)`; unknown versions include available version strings in the normal 404 envelope.
51
+ - `parsed_at` is the authoritative gate: unparsed or missing source rows do not trigger TOC/chunk reads.
52
+ - A missing TOC for an otherwise parsed source is treated as absent while chunks continue to render, as required.
53
+ - Pagination requests `limit + 1`, renders only `limit`, and preserves `version`, `release`, and `section` in next/previous links.
54
+ - HTMX responses render only `partials/spec_doc_show_results.html` with the required outer `#results` element.
55
+ - No JSON contract, storage schema, CLI, MCP, fetch route, version-table link, or synchronous parse behavior was added or changed.
56
+ - The direct task instruction defers parse controls to Task 3, so the page intentionally renders read/source state without a parse form or parse JavaScript despite the broader plan's future parse-form design.
57
+ - Tests use the public `SpecDocService` surface and do not access `_doc_repo`.
58
+
59
+ ## Concerns
60
+
61
+ - The page currently has no parse action by design; Task 3 must add the parse form/job poller integration.
62
+ - The pre-existing untracked plan file remains in the worktree and was intentionally left untouched.