@ngocsangairvds/vsaf 3.2.14 → 3.2.16

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 (1442) hide show
  1. package/bin/vsaf.js +18 -4
  2. package/package.json +1 -1
  3. package/src/config.js +167 -0
  4. package/src/global.js +1 -48
  5. package/src/project.js +1 -0
  6. package/src/utils.js +44 -1
  7. package/tools/vds-scripts/Makefile +9 -31
  8. package/tools/vds-scripts/docker/docker-compose.cli.yml +1 -117
  9. package/tools/vds-scripts/docker/docker-compose.services.yml +1 -40
  10. package/tools/vds-scripts/docker/infrastructure/init-schemas.sql +0 -34
  11. package/tools/vds-scripts/docker/infrastructure/pgbouncer/pgbouncer.ini +2 -6
  12. package/tools/vds-scripts/pyproject.toml +1 -33
  13. package/tools/vds-scripts/uv.lock +80 -1651
  14. package/tools/vds-scripts/vds_cli/pyproject.toml +3 -0
  15. package/tools/vds-scripts/vds_cli/src/vds_cli/cli.py +1 -127
  16. package/tools/vds-scripts/vds_cli/src/vds_cli/commands/lint_cli.py +1 -20
  17. package/tools/vds-scripts/vds_cli/src/vds_cli/router.py +0 -100
  18. package/tools/vds-scripts/vds_cli/tests/conftest.py +0 -2
  19. package/tools/vds-scripts/vds_cli/tests/unit/test_cli.py +0 -25
  20. package/tools/vds-scripts/vds_cli/tests/unit/test_lint_cli.py +2 -2
  21. package/tools/vds-scripts/vds_cli/tests/unit/test_router.py +0 -2
  22. package/tools/vds-scripts/CLOSURE.md +0 -340
  23. package/tools/vds-scripts/ECOSYSTEM-CHANGELOG.md +0 -52
  24. package/tools/vds-scripts/ECOSYSTEM-DOCS.md +0 -602
  25. package/tools/vds-scripts/ECOSYSTEM_ALIGNMENT.md +0 -133
  26. package/tools/vds-scripts/ENV-HYGIENE-OPS-NOTE.md +0 -65
  27. package/tools/vds-scripts/INVESTIGATION-cloud-401.md +0 -103
  28. package/tools/vds-scripts/MEM0_2.0_API_REFERENCE.md +0 -238
  29. package/tools/vds-scripts/PACKAGE_P125B_IMPLEMENTATION_SUMMARY.md +0 -131
  30. package/tools/vds-scripts/PHASE-MERGE-SUMMARY.md +0 -121
  31. package/tools/vds-scripts/PHASES-3-ARCHIVE.md +0 -59
  32. package/tools/vds-scripts/PROJECT_COMPLETION_SUMMARY.md +0 -45
  33. package/tools/vds-scripts/SEARCH-CRASH-REPRO.md +0 -51
  34. package/tools/vds-scripts/analyze_hexagonal.py +0 -217
  35. package/tools/vds-scripts/analyze_profiles.py +0 -60
  36. package/tools/vds-scripts/audit-checklist.xlsx +0 -0
  37. package/tools/vds-scripts/audit_orchestrator/.audit_approvals/approvals_index.json +0 -1
  38. package/tools/vds-scripts/audit_orchestrator/.env.example +0 -85
  39. package/tools/vds-scripts/audit_orchestrator/.github/workflows/audit.yml +0 -47
  40. package/tools/vds-scripts/audit_orchestrator/Dockerfile +0 -92
  41. package/tools/vds-scripts/audit_orchestrator/GOOGLE_SHEETS_IMPLEMENTATION_SUMMARY.md +0 -218
  42. package/tools/vds-scripts/audit_orchestrator/PHASE3_INTEGRATION_SUMMARY.md +0 -268
  43. package/tools/vds-scripts/audit_orchestrator/PHASE7-MERGE-SUMMARY.md +0 -174
  44. package/tools/vds-scripts/audit_orchestrator/README.md +0 -1573
  45. package/tools/vds-scripts/audit_orchestrator/TSK-168-IMPLEMENTATION-SUMMARY.md +0 -191
  46. package/tools/vds-scripts/audit_orchestrator/TSK-196-IMPLEMENTATION-SUMMARY.md +0 -201
  47. package/tools/vds-scripts/audit_orchestrator/alembic/env.py +0 -37
  48. package/tools/vds-scripts/audit_orchestrator/alembic/script.py.mako +0 -28
  49. package/tools/vds-scripts/audit_orchestrator/alembic/versions/0001_initial_audit_state_schema.py +0 -1260
  50. package/tools/vds-scripts/audit_orchestrator/alembic.ini +0 -68
  51. package/tools/vds-scripts/audit_orchestrator/config/category-mapping.json +0 -81
  52. package/tools/vds-scripts/audit_orchestrator/config/profile-timeouts.yaml +0 -17
  53. package/tools/vds-scripts/audit_orchestrator/create_sample.py +0 -55
  54. package/tools/vds-scripts/audit_orchestrator/data/corpus_accuracy_report.json +0 -17
  55. package/tools/vds-scripts/audit_orchestrator/data/exemplar_quality_report.json +0 -1606
  56. package/tools/vds-scripts/audit_orchestrator/data/instruction_plan_fixtures.json +0 -163
  57. package/tools/vds-scripts/audit_orchestrator/data/requirement_exemplars.json +0 -3443
  58. package/tools/vds-scripts/audit_orchestrator/data/requirement_scope_fixtures.json +0 -172
  59. package/tools/vds-scripts/audit_orchestrator/debug_rg.py +0 -46
  60. package/tools/vds-scripts/audit_orchestrator/demo_code_pack.py +0 -127
  61. package/tools/vds-scripts/audit_orchestrator/docs/AGENT_SDK_SELECTION_SPEC.md +0 -720
  62. package/tools/vds-scripts/audit_orchestrator/docs/API.md +0 -804
  63. package/tools/vds-scripts/audit_orchestrator/docs/CONTENT_ANALYSIS_APPROACH.md +0 -1041
  64. package/tools/vds-scripts/audit_orchestrator/docs/CONTENT_SCORING_EVOLUTION_SPEC.md +0 -868
  65. package/tools/vds-scripts/audit_orchestrator/docs/DEPLOYMENT.md +0 -778
  66. package/tools/vds-scripts/audit_orchestrator/docs/LLM_AGENT_AUDIT_SPEC.md +0 -721
  67. package/tools/vds-scripts/audit_orchestrator/docs/LLM_CONTENT_ANALYSIS_SPEC.md +0 -1143
  68. package/tools/vds-scripts/audit_orchestrator/docs/LSP_SETUP_GUIDE.md +0 -221
  69. package/tools/vds-scripts/audit_orchestrator/docs/MULTI_REPO_AUDIT_SPEC.md +0 -951
  70. package/tools/vds-scripts/audit_orchestrator/docs/OLLAMA_EMBEDDINGS_SETUP.md +0 -119
  71. package/tools/vds-scripts/audit_orchestrator/docs/PHASE32_REAL_BENCHMARK_2026-02-08.md +0 -66
  72. package/tools/vds-scripts/audit_orchestrator/docs/PHASE_64_TO_92_HISTORICAL_SPEC.md +0 -1772
  73. package/tools/vds-scripts/audit_orchestrator/docs/TSK-193-flow-trace.md +0 -201
  74. package/tools/vds-scripts/audit_orchestrator/docs/TSK-193-verification.md +0 -124
  75. package/tools/vds-scripts/audit_orchestrator/docs/phase152-hierarchical-query-surface.md +0 -46
  76. package/tools/vds-scripts/audit_orchestrator/examples/bitbucket_metadata_example.json +0 -50
  77. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/README.md +0 -68
  78. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase117_phase118_shared_state.sql +0 -64
  79. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase154_published_pages.sql +0 -28
  80. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase157_dispatch_tables.sql +0 -94
  81. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase157_events.sql +0 -91
  82. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase157_scope_snapshots.sql +0 -24
  83. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase157_status_view.sql +0 -22
  84. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/phase169_dispatch_observability.sql +0 -55
  85. package/tools/vds-scripts/audit_orchestrator/legacy/migrations/state_repair_hardening.sql +0 -24
  86. package/tools/vds-scripts/audit_orchestrator/pyproject.toml +0 -211
  87. package/tools/vds-scripts/audit_orchestrator/pyrightconfig.json +0 -51
  88. package/tools/vds-scripts/audit_orchestrator/pytest.ini +0 -37
  89. package/tools/vds-scripts/audit_orchestrator/reproduce_scanner.py +0 -40
  90. package/tools/vds-scripts/audit_orchestrator/scripts/README.md +0 -116
  91. package/tools/vds-scripts/audit_orchestrator/scripts/benchmark_crawl_modes.py +0 -455
  92. package/tools/vds-scripts/audit_orchestrator/scripts/benchmark_dspy.py +0 -513
  93. package/tools/vds-scripts/audit_orchestrator/scripts/benchmark_nlp_accuracy.py +0 -138
  94. package/tools/vds-scripts/audit_orchestrator/scripts/benchmark_retrieval_modes.py +0 -176
  95. package/tools/vds-scripts/audit_orchestrator/scripts/benchmark_upload_update_mode.py +0 -167
  96. package/tools/vds-scripts/audit_orchestrator/scripts/build_check.py +0 -76
  97. package/tools/vds-scripts/audit_orchestrator/scripts/check_live_progress.py +0 -61
  98. package/tools/vds-scripts/audit_orchestrator/scripts/cli_integration_test.py +0 -400
  99. package/tools/vds-scripts/audit_orchestrator/scripts/index_workspace.py +0 -178
  100. package/tools/vds-scripts/audit_orchestrator/scripts/inspect_route_conformance.py +0 -196
  101. package/tools/vds-scripts/audit_orchestrator/scripts/monitor_postgres.py +0 -145
  102. package/tools/vds-scripts/audit_orchestrator/scripts/optimize_audit.py +0 -462
  103. package/tools/vds-scripts/audit_orchestrator/scripts/verify.py +0 -673
  104. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase111_requirement_analysis.py +0 -375
  105. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase117_cross_repo_evidence.py +0 -77
  106. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase121_short_circuit.py +0 -680
  107. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase122_instruction_handling.py +0 -478
  108. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase125_skill_integration.py +0 -832
  109. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase_36.py +0 -394
  110. package/tools/vds-scripts/audit_orchestrator/scripts/verify_phase_37.py +0 -58
  111. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/__init__.py +0 -17
  112. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/__init__.py +0 -29
  113. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/_langchain_warnings.py +0 -17
  114. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/agentic_investigator.py +0 -4130
  115. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/approval.py +0 -490
  116. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/audit_loop_hooks.py +0 -107
  117. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/audit_state.py +0 -50
  118. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/base.py +0 -4035
  119. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/code_agent.py +0 -667
  120. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/code_analysis_helpers.py +0 -236
  121. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/code_analysis_prompts.py +0 -146
  122. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/docs_agent.py +0 -1234
  123. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/langgraph_workflow.py +0 -2002
  124. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/pydantic_base.py +0 -1227
  125. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/requirement_analysis_agent.py +0 -593
  126. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/security_agent.py +0 -1829
  127. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/security_scanner.py +0 -686
  128. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/skill_tools.py +0 -204
  129. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/synthesis_agent.py +0 -1463
  130. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/tool_efficiency_guard.py +0 -609
  131. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/tool_registry.py +0 -3822
  132. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/__init__.py +0 -52
  133. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/evidence_corpus.py +0 -385
  134. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/filesystem.py +0 -1134
  135. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/lsp.py +0 -458
  136. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/mcp_toolset.py +0 -491
  137. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/skills_toolset.py +0 -997
  138. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/toolsets/vector_evidence.py +0 -842
  139. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/usage_tracker.py +0 -682
  140. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/agents/visualization.py +0 -303
  141. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/analyze_cmds.py +0 -892
  142. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checklist_query/__init__.py +0 -15
  143. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checklist_query/service.py +0 -171
  144. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/__init__.py +0 -20
  145. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/base.py +0 -60
  146. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/bitbucket/__init__.py +0 -6
  147. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/bitbucket/checks.py +0 -257
  148. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/confluence/__init__.py +0 -10
  149. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/confluence/checks.py +0 -78
  150. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/git/__init__.py +0 -6
  151. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/git/file_checks.py +0 -133
  152. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/llm_checks/__init__.py +0 -17
  153. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/llm_checks/api_docs_check.py +0 -80
  154. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/llm_checks/readme_check.py +0 -76
  155. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/llm_checks/security_docs_check.py +0 -78
  156. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/registry.py +0 -402
  157. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/sonarqube/__init__.py +0 -10
  158. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/checks/sonarqube/checks.py +0 -276
  159. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/cli.py +0 -12
  160. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/cli_common.py +0 -128
  161. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/cli_impl.py +0 -9826
  162. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/clients/bitbucket_cli_client.py +0 -187
  163. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/clients/confluence_cli_client.py +0 -977
  164. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/clients/sonarqube_cli_client.py +0 -28
  165. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/__init__.py +0 -21
  166. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/base.py +0 -25
  167. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/bitbucket_downloader.py +0 -644
  168. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/bitbucket_metadata.py +0 -133
  169. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/checklist_parser.py +0 -180
  170. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/completeness/__init__.py +0 -31
  171. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/completeness/bitbucket_probe.py +0 -443
  172. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/completeness/confluence_probe.py +0 -365
  173. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/completeness/freshness_evaluator.py +0 -330
  174. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/completeness/material_completeness_service.py +0 -1079
  175. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/confluence_collector.py +0 -259
  176. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/diagram_extractor.py +0 -280
  177. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/enrichment_extractor.py +0 -200
  178. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/evidence_cache.py +0 -35
  179. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/git_collector.py +0 -148
  180. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/graphify_collector.py +0 -171
  181. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/image_extractor.py +0 -359
  182. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/linked_page_tracker.py +0 -120
  183. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/markdown_converter.py +0 -344
  184. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/material_cache.py +0 -1252
  185. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/material_downloader.py +0 -1165
  186. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/orchestrator.py +0 -168
  187. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/registry_parser.py +0 -3063
  188. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/requirements.py +0 -70
  189. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/runner.py +0 -119
  190. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/collectors/sonarqube_collector.py +0 -113
  191. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config.py +0 -1943
  192. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/__init__.py +0 -23
  193. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/discovery.py +0 -90
  194. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/environment_resolver.py +0 -56
  195. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/evidence.py +0 -78
  196. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/models.py +0 -73
  197. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/precedence.py +0 -10
  198. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/config_resolution/redaction.py +0 -20
  199. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/confluence_connectivity.py +0 -140
  200. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/corpus_cmds.py +0 -278
  201. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/db/__init__.py +0 -7
  202. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/db/alembic_filters.py +0 -57
  203. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/docs/__init__.py +0 -29
  204. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/docs/diataxis_validator.py +0 -687
  205. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/doctor_cmds.py +0 -3295
  206. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/dspy_modules/__init__.py +0 -5
  207. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/dspy_modules/evaluation.py +0 -301
  208. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/dspy_modules/modules.py +0 -172
  209. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/dspy_modules/runtime.py +0 -836
  210. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/dspy_modules/signatures.py +0 -406
  211. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/__init__.py +0 -192
  212. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/ad_hoc_analyzer.py +0 -399
  213. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/aggregator.py +0 -220
  214. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/auditor.py +0 -504
  215. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/batch_evidence_cache.py +0 -111
  216. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/batch_processor.py +0 -4776
  217. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/calibration.py +0 -217
  218. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/checklist_generator.py +0 -1201
  219. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/checklist_projection.py +0 -192
  220. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/checklist_scoping.py +0 -221
  221. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/checkpoint.py +0 -159
  222. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/cl003_shared_lib_guard.py +0 -194
  223. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/companion_context_service.py +0 -445
  224. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/confluence_checklist_contract.py +0 -7425
  225. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/cross_check_rules.py +0 -213
  226. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/deterministic_evaluator.py +0 -237
  227. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/drift_detector.py +0 -157
  228. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/dspy_requirement_classifier.py +0 -640
  229. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/evidence_assembler.py +0 -407
  230. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/evidence_collector.py +0 -119
  231. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/evidence_diversity.py +0 -101
  232. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/gap_analyzer.py +0 -549
  233. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/graduated.py +0 -185
  234. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/grounding_validator.py +0 -287
  235. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/instruction_analyzer.py +0 -882
  236. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/instruction_compliance.py +0 -172
  237. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/llm_row_evaluator.py +0 -9270
  238. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/loader.py +0 -1070
  239. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/manual_check_config.py +0 -136
  240. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/mapping.py +0 -269
  241. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/multi_judge.py +0 -65
  242. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/phase120_checklist_update.py +0 -416
  243. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/profile_scorer.py +0 -427
  244. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/project_evidence_context.py +0 -449
  245. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/project_knowledge_query_service.py +0 -155
  246. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/project_knowledge_store.py +0 -383
  247. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/project_topology.py +0 -1920
  248. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/provider_failure_classifier.py +0 -778
  249. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/readiness_cli_helpers.py +0 -341
  250. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/readiness_extractor.py +0 -303
  251. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/readiness_synthesizer.py +0 -730
  252. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/regression_guard.py +0 -138
  253. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/repo_type_classifier.py +0 -297
  254. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/requirement_analysis.py +0 -1433
  255. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/requirement_classification.py +0 -1725
  256. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/result_merger.py +0 -814
  257. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/route_matrix.py +0 -267
  258. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/row_evaluator.py +0 -9437
  259. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/row_evaluator_runtime.py +0 -1270
  260. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/row_evaluator_types.py +0 -2102
  261. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/rubric.py +0 -592
  262. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/scorer.py +0 -1239
  263. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/section_packs.py +0 -645
  264. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/skill_recommendation.py +0 -1183
  265. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/stability_harness.py +0 -207
  266. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/target_selector.py +0 -841
  267. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/telemetry.py +0 -347
  268. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/template_analyzer.py +0 -469
  269. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/token_tracker.py +0 -111
  270. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/tool_first_planner.py +0 -7905
  271. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/topology_query_service.py +0 -80
  272. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/validator.py +0 -449
  273. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/engine/weight_policy.py +0 -464
  274. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/errors.py +0 -430
  275. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/extract_cmds.py +0 -4887
  276. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/identity.py +0 -146
  277. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/incremental/__init__.py +0 -52
  278. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/incremental/baseline.py +0 -378
  279. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/incremental/change_analyzer.py +0 -407
  280. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/incremental/delta_report.py +0 -189
  281. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/incremental/diff_detector.py +0 -301
  282. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/integrations/__init__.py +0 -3
  283. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/__init__.py +0 -50
  284. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/audit_schemas.py +0 -459
  285. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/codex_oauth.py +0 -340
  286. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/cost_tracker.py +0 -288
  287. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/engine.py +0 -751
  288. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/evaluator.py +0 -245
  289. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/__init__.py +0 -32
  290. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/api_docs_evaluation.py +0 -25
  291. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/gap_analysis.py +0 -31
  292. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/instruction_templates.py +0 -634
  293. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/readme_evaluation.py +0 -25
  294. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/row_evaluation.py +0 -247
  295. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/security_docs_evaluation.py +0 -25
  296. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts/template_analysis.py +0 -25
  297. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/prompts.py +0 -0
  298. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/llm/provider.py +0 -626
  299. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/logging_config.py +0 -577
  300. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/mappings/__init__.py +0 -58
  301. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/mappings/default_checklist_mapping.json +0 -18
  302. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/mappings/vietnamese_checklist_mapping.json +0 -38
  303. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/misc_cmds.py +0 -4689
  304. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/__init__.py +0 -153
  305. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/calibration.py +0 -98
  306. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/checklist.py +0 -921
  307. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/completeness.py +0 -309
  308. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/enrichment.py +0 -58
  309. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/enums.py +0 -97
  310. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/evidence.py +0 -351
  311. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/findings.py +0 -381
  312. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/gaps.py +0 -299
  313. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/graph.py +0 -42
  314. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/multi_judge.py +0 -50
  315. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/readiness.py +0 -309
  316. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/registry.py +0 -386
  317. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/reporting.py +0 -32
  318. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/task.py +0 -549
  319. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/models/template.py +0 -477
  320. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/observability/__init__.py +0 -31
  321. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/observability/metrics.py +0 -404
  322. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/parse_cmds.py +0 -608
  323. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/pdf_cmds.py +0 -208
  324. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/performance_gates.py +0 -224
  325. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/phase151_projection.py +0 -84
  326. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/profiles/__init__.py +0 -65
  327. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/profiles/detection.py +0 -842
  328. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/profiles/models.py +0 -474
  329. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/__init__.py +0 -1
  330. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/_confluence_macros.py +0 -145
  331. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/_field_sanitizer.py +0 -25
  332. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/_table_builder.py +0 -63
  333. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/_vietnamese_templates.py +0 -103
  334. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/bitbucket_link_resolver.py +0 -34
  335. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/checklist_renderer.py +0 -483
  336. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/confluence_publisher.py +0 -3048
  337. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/hierarchy_publisher.py +0 -213
  338. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/live_data_injector.py +0 -152
  339. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/macro_builder.py +0 -101
  340. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/markdown_converter.py +0 -154
  341. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/priority_renderer.py +0 -133
  342. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/project_aggregate_renderer.py +0 -423
  343. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/readiness_renderer.py +0 -186
  344. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/system_doc_hierarchy_renderer.py +0 -382
  345. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/publishers/system_doc_renderer.py +0 -683
  346. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/report_cmds.py +0 -788
  347. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/__init__.py +0 -13
  348. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/aggregation_report.py +0 -86
  349. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/checklist_generator.py +0 -425
  350. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/excel_generator.py +0 -599
  351. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/gap_report.py +0 -131
  352. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/json_generator.py +0 -188
  353. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/markdown_generator.py +0 -595
  354. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/__init__.py +0 -154
  355. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/collector.py +0 -61
  356. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/department_builder.py +0 -77
  357. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/errors.py +0 -9
  358. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/md_renderer.py +0 -386
  359. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/pdf_models.py +0 -95
  360. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/pdf_writer.py +0 -27
  361. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/pdf/repo_project_builders.py +0 -274
  362. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/readiness_report.py +0 -447
  363. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/reporting.py +0 -94
  364. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/reports/sarif_generator.py +0 -519
  365. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/runtime_profiles.py +0 -98
  366. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/seed/__init__.py +0 -29
  367. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/seed/seed_loader.py +0 -561
  368. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/skills/__init__.py +0 -5
  369. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/skills/skill_routing.py +0 -312
  370. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/__init__.py +0 -0
  371. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/base.py +0 -110
  372. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/bitbucket.py +0 -129
  373. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/git_url.py +0 -60
  374. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/github.py +0 -75
  375. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sources/local.py +0 -58
  376. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/spec_sync_validator.py +0 -15
  377. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/state/__init__.py +0 -6285
  378. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/state/readiness_helpers.py +0 -74
  379. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/state/skill_readiness.py +0 -487
  380. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/state/store.py +0 -12927
  381. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/state_cmds.py +0 -1868
  382. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sync/__init__.py +0 -0
  383. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sync/repo_sync.py +0 -409
  384. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/sync_cmds.py +0 -1247
  385. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/utils/__init__.py +0 -3
  386. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/utils/debug_bundle.py +0 -214
  387. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/validators/checklist_validator.py +0 -342
  388. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflow_cmds.py +0 -19147
  389. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/__init__.py +0 -9
  390. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/_test_audit_daily_batch.py +0 -192
  391. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/audit_daily_batch.py +0 -308
  392. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/audit_deep_monthly.py +0 -193
  393. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/audit_drift_scan.py +0 -178
  394. package/tools/vds-scripts/audit_orchestrator/src/vds_audit_orchestrator/workflows/audit_security_daily.py +0 -183
  395. package/tools/vds-scripts/audit_orchestrator/templates/sample_audit_template.xlsx +0 -0
  396. package/tools/vds-scripts/audit_orchestrator/tests/__init__.py +0 -0
  397. package/tools/vds-scripts/audit_orchestrator/tests/_helpers.py +0 -32
  398. package/tools/vds-scripts/audit_orchestrator/tests/collectors/__init__.py +0 -0
  399. package/tools/vds-scripts/audit_orchestrator/tests/collectors/completeness/__init__.py +0 -0
  400. package/tools/vds-scripts/audit_orchestrator/tests/collectors/completeness/test_bitbucket_probe.py +0 -403
  401. package/tools/vds-scripts/audit_orchestrator/tests/collectors/completeness/test_confluence_probe.py +0 -423
  402. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_bitbucket_downloader.py +0 -289
  403. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_image_extractor.py +0 -260
  404. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_markdown_converter.py +0 -57
  405. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_material_cache.py +0 -197
  406. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_material_downloader.py +0 -550
  407. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_registry_parser.py +0 -3514
  408. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_registry_parser_department_entry.py +0 -214
  409. package/tools/vds-scripts/audit_orchestrator/tests/collectors/test_registry_parser_flow.py +0 -200
  410. package/tools/vds-scripts/audit_orchestrator/tests/conftest.py +0 -988
  411. package/tools/vds-scripts/audit_orchestrator/tests/engine/__init__.py +0 -0
  412. package/tools/vds-scripts/audit_orchestrator/tests/engine/test_calibration.py +0 -48
  413. package/tools/vds-scripts/audit_orchestrator/tests/engine/test_confluence_checklist_phase22_helpers.py +0 -6065
  414. package/tools/vds-scripts/audit_orchestrator/tests/engine/test_multi_judge.py +0 -62
  415. package/tools/vds-scripts/audit_orchestrator/tests/engine/test_stability_harness.py +0 -61
  416. package/tools/vds-scripts/audit_orchestrator/tests/engine/test_structured_metadata.py +0 -419
  417. package/tools/vds-scripts/audit_orchestrator/tests/factories/__init__.py +0 -0
  418. package/tools/vds-scripts/audit_orchestrator/tests/factories/models.py +0 -534
  419. package/tools/vds-scripts/audit_orchestrator/tests/factories/templates.py +0 -241
  420. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/__init__.py +0 -0
  421. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/diagrams/__init__.py +0 -0
  422. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/diagrams/compressed.drawio +0 -2
  423. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/diagrams/mockup.bmpr +0 -0
  424. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/diagrams/simple.drawio +0 -26
  425. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/__init__.py +0 -0
  426. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/bitbucket/__init__.py +0 -0
  427. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/bitbucket/branch_permissions_cli.json +0 -26
  428. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/bitbucket/branch_permissions_direct.json +0 -24
  429. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/bitbucket/repo_conditions_cli.json +0 -14
  430. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/bitbucket/repo_conditions_direct.json +0 -12
  431. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/confluence/__init__.py +0 -0
  432. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/confluence/page_cli.json +0 -7
  433. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/confluence/page_direct.json +0 -7
  434. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/confluence/search_cli.json +0 -11
  435. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/confluence/search_direct.json +0 -7
  436. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/sonarqube/__init__.py +0 -0
  437. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/sonarqube/quality_gate_cli.json +0 -12
  438. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/golden/sonarqube/quality_gate_direct.json +0 -12
  439. package/tools/vds-scripts/audit_orchestrator/tests/fixtures/requirement_strategy_phase115.json +0 -118
  440. package/tools/vds-scripts/audit_orchestrator/tests/integration/__init__.py +0 -0
  441. package/tools/vds-scripts/audit_orchestrator/tests/integration/conftest.py +0 -107
  442. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/__init__.py +0 -0
  443. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/expected_outcomes.md +0 -50
  444. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/__init__.py +0 -0
  445. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/auth.py +0 -27
  446. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/config.py +0 -16
  447. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/db.py +0 -24
  448. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/main.py +0 -18
  449. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/src/__init__.py +0 -1
  450. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_audit_repo/src/utils.py +0 -22
  451. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_checklist_template.json +0 -110
  452. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/__init__.py +0 -0
  453. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/code_evidence_pack.json +0 -40
  454. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/manifest.json +0 -49
  455. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/__init__.py +0 -0
  456. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/__init__.py +0 -0
  457. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/brd.md +0 -19
  458. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/design.md +0 -32
  459. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/security.md +0 -23
  460. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/srs.md +0 -25
  461. package/tools/vds-scripts/audit_orchestrator/tests/integration/fixtures/mock_evidence/projects/mock-audit-project/test.md +0 -30
  462. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_checkpoint_merge.py +0 -1371
  463. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_decoupling_route_p149.py +0 -176
  464. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_gap_analyzer_batch_p149.py +0 -151
  465. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_hybrid_search.py +0 -799
  466. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_mcp_integration.py +0 -741
  467. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_merge_ranking_p149.py +0 -98
  468. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_modality_mismatch_p149.py +0 -171
  469. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_phase117_118_storage.py +0 -350
  470. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_phase121_short_circuit.py +0 -732
  471. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_phase18_workflow.py +0 -223
  472. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_phase48_e2e_verification.py +0 -763
  473. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_phase81_doc_anchor_regression.py +0 -252
  474. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_provider_failure_finding_p149.py +0 -339
  475. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_readiness_e2e.py +0 -430
  476. package/tools/vds-scripts/audit_orchestrator/tests/integration/test_refined_workflow.py +0 -1180
  477. package/tools/vds-scripts/audit_orchestrator/tests/pdf/__init__.py +0 -0
  478. package/tools/vds-scripts/audit_orchestrator/tests/pdf/snapshots/__init__.py +0 -0
  479. package/tools/vds-scripts/audit_orchestrator/tests/pdf/snapshots/department_renderer.md +0 -24
  480. package/tools/vds-scripts/audit_orchestrator/tests/pdf/snapshots/project_renderer.md +0 -8
  481. package/tools/vds-scripts/audit_orchestrator/tests/pdf/snapshots/repo_renderer.md +0 -10
  482. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_department_pdf.py +0 -112
  483. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_e2e_pdf.py +0 -135
  484. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_idempotency.py +0 -45
  485. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_md_renderer.py +0 -46
  486. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_pdf_cmds.py +0 -97
  487. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_pdf_snapshot.py +0 -77
  488. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_pdf_writer.py +0 -65
  489. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_project_builder.py +0 -199
  490. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_public_api.py +0 -135
  491. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_repo_builder.py +0 -246
  492. package/tools/vds-scripts/audit_orchestrator/tests/pdf/test_workflow_pdf_flags.py +0 -36
  493. package/tools/vds-scripts/audit_orchestrator/tests/property/__init__.py +0 -0
  494. package/tools/vds-scripts/audit_orchestrator/tests/property/test_properties.py +0 -807
  495. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/__init__.py +0 -0
  496. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_agent_error_compat.py +0 -38
  497. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_agentic_skill_policy_skip.py +0 -234
  498. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_base_event_stream_logging.py +0 -785
  499. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_base_timeout_policy.py +0 -277
  500. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_base_trace_payload_sanitization.py +0 -92
  501. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_code_agent.py +0 -2311
  502. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_code_agent_re_exports.py +0 -25
  503. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_code_analysis_helpers.py +0 -94
  504. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_create_audit_agent_reasoning_effort.py +0 -69
  505. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_docs_agent.py +0 -2044
  506. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_langgraph_workflow_efficiency_metrics.py +0 -71
  507. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_output_validators.py +0 -317
  508. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_phase41_toolsets.py +0 -6427
  509. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_pydantic_ai_models.py +0 -1219
  510. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_pydantic_base_url_resolution.py +0 -84
  511. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_security_agent.py +0 -2069
  512. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_skill_manager_focus.py +0 -439
  513. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_synthesis_agent.py +0 -1195
  514. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_tool_efficiency_guard_fr120.py +0 -683
  515. package/tools/vds-scripts/audit_orchestrator/tests/test_agents/test_toolsets.py +0 -716
  516. package/tools/vds-scripts/audit_orchestrator/tests/test_aggregator_p149.py +0 -171
  517. package/tools/vds-scripts/audit_orchestrator/tests/test_alembic_migrations.py +0 -287
  518. package/tools/vds-scripts/audit_orchestrator/tests/test_anchor_allowlist_p149.py +0 -273
  519. package/tools/vds-scripts/audit_orchestrator/tests/test_audit_otel.py +0 -283
  520. package/tools/vds-scripts/audit_orchestrator/tests/test_checklist_models.py +0 -583
  521. package/tools/vds-scripts/audit_orchestrator/tests/test_checks/__init__.py +0 -0
  522. package/tools/vds-scripts/audit_orchestrator/tests/test_checks/test_base_check.py +0 -211
  523. package/tools/vds-scripts/audit_orchestrator/tests/test_checks/test_llm_checks.py +0 -126
  524. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/__init__.py +0 -0
  525. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_analyze_command.py +0 -400
  526. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_archive_stale_page_cli.py +0 -217
  527. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_bitbucket_metadata_cli.py +0 -354
  528. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_cli_impl_profile_availability.py +0 -114
  529. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_codex_profile.py +0 -174
  530. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_compare_backends_cli.py +0 -449
  531. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_confluence_parent_auto_resolve.py +0 -451
  532. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_corpus_purge_cli.py +0 -290
  533. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_credentials_preflight.py +0 -106
  534. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_debug_bundle.py +0 -37
  535. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_deprecation_phase157.py +0 -484
  536. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_dispatch_concurrency_diagnostics.py +0 -758
  537. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_check_confluence_cli.py +0 -320
  538. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_codex.py +0 -187
  539. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_corpus_status_cli.py +0 -236
  540. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_correlation_cli.py +0 -128
  541. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_crawl_status_cli.py +0 -192
  542. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_credentials_cli.py +0 -86
  543. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_dispatch_status_cli.py +0 -421
  544. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_heartbeat_phase169.py +0 -173
  545. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_hierarchy_status_cli.py +0 -199
  546. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_locks_cli.py +0 -134
  547. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_logs_follow_cli.py +0 -305
  548. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_migration.py +0 -333
  549. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_profile_availability_cli.py +0 -151
  550. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_doctor_skills_policy_cli.py +0 -153
  551. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_evidence_quality_cli.py +0 -307
  552. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_export_debug_bundle_phase36.py +0 -60
  553. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_export_git_manifest_cli.py +0 -172
  554. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_file_removal_phase157e.py +0 -770
  555. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_grounding_classifier.py +0 -226
  556. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_logging.py +0 -49
  557. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_materials_cli.py +0 -9127
  558. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_metadata_completeness_phase92.py +0 -364
  559. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_parent_dispatch_finalization_phase168f.py +0 -111
  560. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_parse_cli.py +0 -590
  561. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_phase117_118_feature_flags.py +0 -219
  562. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_phase164_control_plane.py +0 -718
  563. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_phase165_runner_scripts.py +0 -230
  564. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_preparation_classifications.py +0 -146
  565. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_prepare_cli.py +0 -398
  566. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_publication_quality_gate.py +0 -126
  567. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_publish_system_doc_cli.py +0 -158
  568. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_query_checklist_cli.py +0 -219
  569. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_readiness_cli.py +0 -673
  570. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_readiness_cli_integration.py +0 -689
  571. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_removed_flags_phase92.py +0 -36
  572. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_report_cmds.py +0 -1317
  573. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_run_history_index.py +0 -57
  574. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_run_management.py +0 -1194
  575. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_runtime_profiles_cli.py +0 -1658
  576. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_smart_run_selection.py +0 -1562
  577. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_state_cli.py +0 -2467
  578. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_state_migration.py +0 -339
  579. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_sync_repos_debug_artifacts.py +0 -1109
  580. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_upload_results_cli.py +0 -809
  581. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_validate_checklist.py +0 -178
  582. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_validate_checklist_cli.py +0 -110
  583. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_validate_spec_sync_cli.py +0 -519
  584. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_default_parameters_baseline.py +0 -101
  585. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_options.py +0 -7896
  586. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_project_db_modes.py +0 -6516
  587. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_project_project_scope.py +0 -831
  588. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_project_target.py +0 -611
  589. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_projects_phase131_lifecycle.py +0 -2488
  590. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_projects_phase131_scaffolding.py +0 -96
  591. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_row_key_guard.py +0 -78
  592. package/tools/vds-scripts/audit_orchestrator/tests/test_cli/test_workflow_summary_artifacts.py +0 -1872
  593. package/tools/vds-scripts/audit_orchestrator/tests/test_cli_paths_phase2.py +0 -45
  594. package/tools/vds-scripts/audit_orchestrator/tests/test_clients/__init__.py +0 -0
  595. package/tools/vds-scripts/audit_orchestrator/tests/test_clients/test_bitbucket_cli_client.py +0 -124
  596. package/tools/vds-scripts/audit_orchestrator/tests/test_clients/test_cli_parity.py +0 -110
  597. package/tools/vds-scripts/audit_orchestrator/tests/test_clients/test_confluence_cli_client.py +0 -1149
  598. package/tools/vds-scripts/audit_orchestrator/tests/test_clients/test_sonarqube_cli_client.py +0 -19
  599. package/tools/vds-scripts/audit_orchestrator/tests/test_collectors/__init__.py +0 -0
  600. package/tools/vds-scripts/audit_orchestrator/tests/test_collectors/test_linked_page_tracker.py +0 -118
  601. package/tools/vds-scripts/audit_orchestrator/tests/test_companion_context_service.py +0 -230
  602. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/__init__.py +0 -0
  603. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/conftest.py +0 -11
  604. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_compile_artifact.py +0 -465
  605. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_cross_provider_critique.py +0 -120
  606. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_cross_provider_critique_e2e.py +0 -75
  607. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_evaluation.py +0 -515
  608. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_runtime_loader.py +0 -537
  609. package/tools/vds-scripts/audit_orchestrator/tests/test_dspy_modules/test_signatures_normalization.py +0 -172
  610. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/__init__.py +0 -0
  611. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_auditor_applicability.py +0 -68
  612. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_checklist_generator.py +0 -1252
  613. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_checklist_projection.py +0 -54
  614. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_confluence_checklist_projection_consistency.py +0 -1696
  615. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_critique_merger_matrix.py +0 -120
  616. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_cross_check_rules.py +0 -459
  617. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_cross_provider_critique.py +0 -55
  618. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_doc_loader.py +0 -73
  619. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_drift_detector.py +0 -34
  620. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_evidence_collectors.py +0 -93
  621. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_lease_timeout.py +0 -114
  622. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_loader.py +0 -350
  623. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_loader_parity.py +0 -179
  624. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_low_confidence_reeval.py +0 -691
  625. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_phase145a_completion.py +0 -209
  626. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_phase31_row_consistency_retry_benchmark.py +0 -150
  627. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_profile_detector.py +0 -286
  628. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_regression_guard.py +0 -53
  629. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_result_merger.py +0 -619
  630. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_row_evaluator.py +0 -15783
  631. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_row_failover.py +0 -215
  632. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_scorer.py +0 -597
  633. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_skill_breakdown_telemetry_fr137.py +0 -421
  634. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_targeted_auto_merge.py +0 -229
  635. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_timeout_failover.py +0 -488
  636. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_timeout_telemetry.py +0 -73
  637. package/tools/vds-scripts/audit_orchestrator/tests/test_engine/test_validator.py +0 -419
  638. package/tools/vds-scripts/audit_orchestrator/tests/test_incremental/__init__.py +0 -0
  639. package/tools/vds-scripts/audit_orchestrator/tests/test_incremental/test_diff_detector.py +0 -111
  640. package/tools/vds-scripts/audit_orchestrator/tests/test_infra_persistence.py +0 -291
  641. package/tools/vds-scripts/audit_orchestrator/tests/test_integration/__init__.py +0 -0
  642. package/tools/vds-scripts/audit_orchestrator/tests/test_integration/test_phase3_integration.py +0 -516
  643. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/__init__.py +0 -0
  644. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_cache.py +0 -670
  645. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_codex_model_builder.py +0 -281
  646. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_codex_oauth.py +0 -330
  647. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_codex_streaming.py +0 -433
  648. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_cost_tracker.py +0 -27
  649. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_engine.py +0 -876
  650. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_evaluator.py +0 -212
  651. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_instruction_templates.py +0 -639
  652. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_prompt_metadata.py +0 -97
  653. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_prompts.py +0 -660
  654. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_provider.py +0 -330
  655. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_provider_contract_sync.py +0 -18
  656. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_reasoning_effort_validation.py +0 -565
  657. package/tools/vds-scripts/audit_orchestrator/tests/test_llm/test_schemas.py +0 -827
  658. package/tools/vds-scripts/audit_orchestrator/tests/test_logging_config.py +0 -297
  659. package/tools/vds-scripts/audit_orchestrator/tests/test_models/__init__.py +0 -0
  660. package/tools/vds-scripts/audit_orchestrator/tests/test_models/test_enums.py +0 -185
  661. package/tools/vds-scripts/audit_orchestrator/tests/test_models/test_findings.py +0 -1159
  662. package/tools/vds-scripts/audit_orchestrator/tests/test_models/test_project_profile.py +0 -307
  663. package/tools/vds-scripts/audit_orchestrator/tests/test_models/test_registry.py +0 -532
  664. package/tools/vds-scripts/audit_orchestrator/tests/test_models/test_template.py +0 -708
  665. package/tools/vds-scripts/audit_orchestrator/tests/test_observability/__init__.py +0 -0
  666. package/tools/vds-scripts/audit_orchestrator/tests/test_observability/test_metrics.py +0 -60
  667. package/tools/vds-scripts/audit_orchestrator/tests/test_paths_config_phase2.py +0 -21
  668. package/tools/vds-scripts/audit_orchestrator/tests/test_performance/__init__.py +0 -0
  669. package/tools/vds-scripts/audit_orchestrator/tests/test_performance/test_fr79_performance_guardrails.py +0 -199
  670. package/tools/vds-scripts/audit_orchestrator/tests/test_phase156_hardening.py +0 -498
  671. package/tools/vds-scripts/audit_orchestrator/tests/test_phase93_regression_guards.py +0 -123
  672. package/tools/vds-scripts/audit_orchestrator/tests/test_pipeline_integration.py +0 -517
  673. package/tools/vds-scripts/audit_orchestrator/tests/test_profiles/__init__.py +0 -0
  674. package/tools/vds-scripts/audit_orchestrator/tests/test_profiles/test_detection.py +0 -146
  675. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/__init__.py +0 -0
  676. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_bitbucket_link_resolver.py +0 -55
  677. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_checklist_renderer.py +0 -84
  678. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_checklist_renderer_projection.py +0 -97
  679. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_confluence_macros.py +0 -58
  680. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_confluence_publisher.py +0 -2171
  681. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_evidence_links.py +0 -129
  682. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_field_sanitizer.py +0 -108
  683. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_hierarchy_publisher.py +0 -134
  684. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_incremental_plan_parser.py +0 -62
  685. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_live_data_injector.py +0 -48
  686. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_macro_builder.py +0 -22
  687. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_p161_confluence_optimization.py +0 -168
  688. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_priority_renderer.py +0 -96
  689. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_project_aggregate_renderer.py +0 -364
  690. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_storage_validation.py +0 -273
  691. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_summary_refactor.py +0 -118
  692. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_system_doc_hierarchy.py +0 -50
  693. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_table_builder.py +0 -23
  694. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_vietnamese_templates.py +0 -37
  695. package/tools/vds-scripts/audit_orchestrator/tests/test_publishers/test_wiring_integration.py +0 -290
  696. package/tools/vds-scripts/audit_orchestrator/tests/test_reports/__init__.py +0 -0
  697. package/tools/vds-scripts/audit_orchestrator/tests/test_reports/test_aggregation_report.py +0 -181
  698. package/tools/vds-scripts/audit_orchestrator/tests/test_reports/test_checklist_generator.py +0 -258
  699. package/tools/vds-scripts/audit_orchestrator/tests/test_reports/test_gap_report.py +0 -73
  700. package/tools/vds-scripts/audit_orchestrator/tests/test_reports/test_json_generator.py +0 -317
  701. package/tools/vds-scripts/audit_orchestrator/tests/test_result_merger_p149.py +0 -347
  702. package/tools/vds-scripts/audit_orchestrator/tests/test_route_mode_p149.py +0 -178
  703. package/tools/vds-scripts/audit_orchestrator/tests/test_rubric_parser.py +0 -179
  704. package/tools/vds-scripts/audit_orchestrator/tests/test_scorer.py +0 -110
  705. package/tools/vds-scripts/audit_orchestrator/tests/test_state/__init__.py +0 -0
  706. package/tools/vds-scripts/audit_orchestrator/tests/test_state/test_sparse_coverage.py +0 -117
  707. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow/__init__.py +0 -0
  708. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow/test_langgraph_workflow.py +0 -2072
  709. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow/test_p161_runtime_hardening.py +0 -341
  710. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow_cmds_p149.py +0 -112
  711. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow_cmds_p172.py +0 -126
  712. package/tools/vds-scripts/audit_orchestrator/tests/test_workflow_guidance_p150.py +0 -95
  713. package/tools/vds-scripts/audit_orchestrator/tests/unit/__init__.py +0 -0
  714. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/__init__.py +0 -0
  715. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_agentic_investigator_phase115.py +0 -42
  716. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_requirement_analysis_agent.py +0 -412
  717. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_security_agent_updates.py +0 -131
  718. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_security_scanner.py +0 -397
  719. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_skill_executor.py +0 -316
  720. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_skill_fallback.py +0 -299
  721. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_skill_policy.py +0 -520
  722. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_skill_telemetry.py +0 -306
  723. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_synthesis_fixes.py +0 -761
  724. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_argument_robustness.py +0 -272
  725. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_registry.py +0 -2548
  726. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_registry_ast_grep.py +0 -87
  727. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_registry_phase123_scoping.py +0 -353
  728. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_registry_phase94_ff.py +0 -445
  729. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_tool_registry_vector_search_phase115.py +0 -35
  730. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_utils.py +0 -1007
  731. package/tools/vds-scripts/audit_orchestrator/tests/unit/agents/test_vector_evidence_toolset.py +0 -622
  732. package/tools/vds-scripts/audit_orchestrator/tests/unit/cli/__init__.py +0 -0
  733. package/tools/vds-scripts/audit_orchestrator/tests/unit/cli/test_workflow_cli.py +0 -123
  734. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/__init__.py +0 -0
  735. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/test_cache_guard.py +0 -479
  736. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/test_checklist_parser_phase120.py +0 -55
  737. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/test_diagram_extractor.py +0 -467
  738. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/test_enrichment_extractor.py +0 -59
  739. package/tools/vds-scripts/audit_orchestrator/tests/unit/collectors/test_graphify_collector.py +0 -158
  740. package/tools/vds-scripts/audit_orchestrator/tests/unit/completeness/__init__.py +0 -0
  741. package/tools/vds-scripts/audit_orchestrator/tests/unit/completeness/test_completeness.py +0 -563
  742. package/tools/vds-scripts/audit_orchestrator/tests/unit/completeness/test_freshness_evaluator.py +0 -493
  743. package/tools/vds-scripts/audit_orchestrator/tests/unit/completeness/test_material_cache_metrics.py +0 -365
  744. package/tools/vds-scripts/audit_orchestrator/tests/unit/completeness/test_material_completeness_service.py +0 -2736
  745. package/tools/vds-scripts/audit_orchestrator/tests/unit/config_resolution/__init__.py +0 -0
  746. package/tools/vds-scripts/audit_orchestrator/tests/unit/config_resolution/test_discovery.py +0 -47
  747. package/tools/vds-scripts/audit_orchestrator/tests/unit/config_resolution/test_redaction.py +0 -15
  748. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/__init__.py +0 -0
  749. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_ad_hoc_analyzer.py +0 -576
  750. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_agent_loop.py +0 -1896
  751. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_anchor_filter_cl003.py +0 -181
  752. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_batch_evidence_cache.py +0 -155
  753. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_batch_processor.py +0 -3608
  754. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_checklist_contract.py +0 -55
  755. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_checklist_scoping.py +0 -371
  756. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_config_companion_phase123.py +0 -142
  757. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_config_evidence_phase123.py +0 -249
  758. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_confluence_checklist_contract_export_parity.py +0 -813
  759. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_cross_repo_config_phase122.py +0 -613
  760. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_dspy_requirement_classifier.py +0 -517
  761. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_evidence_diversity.py +0 -144
  762. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_evidence_truncation.py +0 -108
  763. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_grounding_validator.py +0 -127
  764. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_guidance_injection_phase120.py +0 -105
  765. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_instruction_analysis_phase122.py +0 -761
  766. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_instruction_pre_filter_phase167.py +0 -334
  767. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_llm_row_evaluator_retries.py +0 -3684
  768. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_loader_phase123.py +0 -345
  769. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_manual_check_gating_phase122.py +0 -474
  770. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_parallel_eval.py +0 -263
  771. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_phase122_verifier_phase122.py +0 -169
  772. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_phase166_route_failover.py +0 -437
  773. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_post_eval_cl003_shared_lib.py +0 -267
  774. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_postproc_streaming.py +0 -194
  775. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_pre_eval_gating_phase122.py +0 -362
  776. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_prepare_topology_coverage.py +0 -247
  777. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_private_dns_sanitization_phase104.py +0 -397
  778. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_project_evidence_context.py +0 -450
  779. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_project_knowledge_store.py +0 -487
  780. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_project_topology.py +0 -1142
  781. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_provider_failure_classifier.py +0 -195
  782. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_readiness_extractor.py +0 -496
  783. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_readiness_synthesizer.py +0 -653
  784. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_repo_type_classifier.py +0 -303
  785. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_analysis.py +0 -508
  786. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_analysis_execution_scope.py +0 -239
  787. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_analysis_phase114.py +0 -919
  788. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_analysis_phase115.py +0 -97
  789. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_analysis_shared_lib.py +0 -340
  790. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_classification_drift.py +0 -729
  791. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_classification_nlp.py +0 -670
  792. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_requirement_scope_phase122.py +0 -615
  793. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_route_matrix.py +0 -258
  794. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_route_override.py +0 -141
  795. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_routing_precision.py +0 -650
  796. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_row_evaluator_dual_evidence.py +0 -2987
  797. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_row_evaluator_instruction_runtime_phase122.py +0 -365
  798. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_row_evaluator_runtime.py +0 -830
  799. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_runtime_hardening_phase122.py +0 -225
  800. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_scoped_na_skip.py +0 -107
  801. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_scoring_enhancements.py +0 -404
  802. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_shared_library_retrieval_phase123.py +0 -441
  803. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_shared_library_routing_phase123.py +0 -279
  804. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_shared_resource_indexing_phase122.py +0 -188
  805. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_skill_recommendation.py +0 -225
  806. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_skill_routing_cl003_shared_lib.py +0 -338
  807. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_skills_toolset.py +0 -319
  808. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_stability_metric.py +0 -60
  809. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_target_selector.py +0 -958
  810. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_token_tracker.py +0 -121
  811. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_token_wiring.py +0 -119
  812. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_tool_first_planner.py +0 -7103
  813. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_topology_knowledge_persistence.py +0 -332
  814. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_topology_query_service.py +0 -55
  815. package/tools/vds-scripts/audit_orchestrator/tests/unit/engine/test_unverified_ref_retry.py +0 -909
  816. package/tools/vds-scripts/audit_orchestrator/tests/unit/models/__init__.py +0 -0
  817. package/tools/vds-scripts/audit_orchestrator/tests/unit/models/test_evidence.py +0 -515
  818. package/tools/vds-scripts/audit_orchestrator/tests/unit/models/test_gaps.py +0 -422
  819. package/tools/vds-scripts/audit_orchestrator/tests/unit/models/test_readiness.py +0 -428
  820. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/__init__.py +0 -0
  821. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_confluence_hierarchy.py +0 -227
  822. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_project_title_generation.py +0 -335
  823. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_publisher_registry_helpers.py +0 -290
  824. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_publisher_registry_integration.py +0 -557
  825. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_readiness_renderer.py +0 -381
  826. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_repo_title_consistency.py +0 -266
  827. package/tools/vds-scripts/audit_orchestrator/tests/unit/publishers/test_upload_hierarchy_integration.py +0 -470
  828. package/tools/vds-scripts/audit_orchestrator/tests/unit/scripts/__init__.py +0 -0
  829. package/tools/vds-scripts/audit_orchestrator/tests/unit/scripts/test_benchmark_dspy.py +0 -177
  830. package/tools/vds-scripts/audit_orchestrator/tests/unit/scripts/test_benchmark_nlp_accuracy.py +0 -72
  831. package/tools/vds-scripts/audit_orchestrator/tests/unit/scripts/test_benchmark_retrieval_modes.py +0 -123
  832. package/tools/vds-scripts/audit_orchestrator/tests/unit/scripts/test_verify_phase111_requirement_analysis.py +0 -409
  833. package/tools/vds-scripts/audit_orchestrator/tests/unit/seed/__init__.py +0 -0
  834. package/tools/vds-scripts/audit_orchestrator/tests/unit/seed/test_seed_chain_cli.py +0 -277
  835. package/tools/vds-scripts/audit_orchestrator/tests/unit/seed/test_seed_loader.py +0 -502
  836. package/tools/vds-scripts/audit_orchestrator/tests/unit/skills/__init__.py +0 -0
  837. package/tools/vds-scripts/audit_orchestrator/tests/unit/skills/test_skill_routing.py +0 -209
  838. package/tools/vds-scripts/audit_orchestrator/tests/unit/sources/__init__.py +0 -0
  839. package/tools/vds-scripts/audit_orchestrator/tests/unit/sources/test_bitbucket_source.py +0 -66
  840. package/tools/vds-scripts/audit_orchestrator/tests/unit/sources/test_non_retryable_markers.py +0 -88
  841. package/tools/vds-scripts/audit_orchestrator/tests/unit/sources/test_repo_info.py +0 -212
  842. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/__init__.py +0 -0
  843. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_completeness.py +0 -598
  844. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_dispatch_events_contract_phase169.py +0 -100
  845. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_dispatch_hardening_phase158.py +0 -392
  846. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_dispatch_persistence_phase157.py +0 -914
  847. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_embedding_client.py +0 -64
  848. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_get_latest_completed_run.py +0 -313
  849. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_heartbeat_phase169.py +0 -109
  850. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_hybrid_search.py +0 -398
  851. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_normalize_url.py +0 -262
  852. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_phase152_query_surface.py +0 -59
  853. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_phase98_confluence_document_model.py +0 -202
  854. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_published_pages.py +0 -754
  855. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_readiness_helpers.py +0 -193
  856. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_run_ledger.py +0 -522
  857. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_run_management.py +0 -378
  858. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_schema_contract_phase170.py +0 -755
  859. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_state_cmds.py +0 -231
  860. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_state_loaders.py +0 -2151
  861. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_state_run_api.py +0 -2226
  862. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_store.py +0 -1435
  863. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_store_dispatch.py +0 -646
  864. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_store_dispatch_status_view.py +0 -181
  865. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_store_scope.py +0 -213
  866. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_utilization_persist_phase169.py +0 -77
  867. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_vds_search.py +0 -263
  868. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_vector_index_api.py +0 -319
  869. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_vector_index_runtime.py +0 -175
  870. package/tools/vds-scripts/audit_orchestrator/tests/unit/state/test_vector_index_store.py +0 -1756
  871. package/tools/vds-scripts/audit_orchestrator/tests/unit/sync/__init__.py +0 -0
  872. package/tools/vds-scripts/audit_orchestrator/tests/unit/sync/test_repo_sync.py +0 -257
  873. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_artifact_exclusion.py +0 -119
  874. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_auto_promote_phase158.py +0 -337
  875. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_carry_forward_artifact_filtering.py +0 -317
  876. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_checklist_precache_p160a.py +0 -416
  877. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_cli_decomposition_fr219.py +0 -269
  878. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_code_chunk_carry_forward.py +0 -203
  879. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_config_coherence.py +0 -180
  880. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_config_secret_policy.py +0 -522
  881. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_corpus_project_id_migration.py +0 -318
  882. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_corpus_status_diagnostics.py +0 -239
  883. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_department_priority_ordering.py +0 -131
  884. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_dispatch_coordinator_phase158.py +0 -402
  885. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_dispatch_job_identity_p167a.py +0 -238
  886. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_dispatch_ramp_up_phase171.py +0 -434
  887. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_dispatcher.py +0 -911
  888. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_doc_type_en_inference.py +0 -246
  889. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_early_exit_unchunked_repos.py +0 -111
  890. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_errors.py +0 -237
  891. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_errors_taxonomy.py +0 -83
  892. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_extract_chunking_config_phase98.py +0 -73
  893. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_extract_cmds_state_helpers.py +0 -33
  894. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_extract_docs_code_chunking.py +0 -260
  895. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_finalize_dispatch_run_phase168.py +0 -341
  896. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_identity.py +0 -221
  897. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_infrastructure_detection.py +0 -441
  898. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_junction_table_phase95.py +0 -259
  899. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_late_binding_assignment_p167c.py +0 -286
  900. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_misc_cmds_fr224_225_hardening.py +0 -194
  901. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_p172_integration.py +0 -306
  902. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_parent_provider_preflight.py +0 -118
  903. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_performance_gates_phase92.py +0 -141
  904. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_performance_gates_phase93.py +0 -50
  905. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase115_search_strategy.py +0 -106
  906. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase154_title_consistency.py +0 -117
  907. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase155_param_forwarding.py +0 -304
  908. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase158_concurrency_defaults.py +0 -207
  909. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase170_doctor_schema.py +0 -319
  910. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase170_regression.py +0 -334
  911. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase94_corpus_lifecycle.py +0 -307
  912. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_phase96_repo_key_migration.py +0 -305
  913. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_pipelined_scheduling.py +0 -130
  914. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_profile_availability_probe.py +0 -616
  915. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_profile_aware_row_timeout.py +0 -102
  916. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_profile_timeout_stagger_p160cd.py +0 -205
  917. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_progress_summary_phase169.py +0 -96
  918. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_registry_checklist_diagnostics.py +0 -124
  919. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_resume_manifest_p167b.py +0 -268
  920. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_risk_mitigations_p160e1.py +0 -348
  921. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_single_row_shards_p160b.py +0 -357
  922. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_state_repo_discovery.py +0 -504
  923. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_sync_metadata_entries.py +0 -57
  924. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_task_models.py +0 -1796
  925. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_utilization_telemetry_p167e.py +0 -259
  926. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_vietnamese_fts_hardening.py +0 -160
  927. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_workflow_phase98_enrichment.py +0 -92
  928. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_workflow_project_merge_materialization.py +0 -322
  929. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_workflow_row_key_migration_guard.py +0 -88
  930. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_workflow_short_circuit_phase121.py +0 -564
  931. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_workflow_single_target_row_context.py +0 -49
  932. package/tools/vds-scripts/audit_orchestrator/tests/unit/test_zero_result_messaging.py +0 -76
  933. package/tools/vds-scripts/bandit-report.json +0 -2974
  934. package/tools/vds-scripts/brd_orchestrator/README.md +0 -29
  935. package/tools/vds-scripts/brd_orchestrator/pyproject.toml +0 -63
  936. package/tools/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/__init__.py +0 -17
  937. package/tools/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/cli.py +0 -187
  938. package/tools/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/validator.py +0 -121
  939. package/tools/vds-scripts/brd_orchestrator/tests/__init__.py +0 -0
  940. package/tools/vds-scripts/brd_orchestrator/tests/test_cli.py +0 -62
  941. package/tools/vds-scripts/brd_orchestrator/tests/test_validator.py +0 -33
  942. package/tools/vds-scripts/circular_dependency_orchestrator/README.md +0 -30
  943. package/tools/vds-scripts/circular_dependency_orchestrator/pyproject.toml +0 -43
  944. package/tools/vds-scripts/circular_dependency_orchestrator/src/vds_circular_dependency_orchestrator/__init__.py +0 -16
  945. package/tools/vds-scripts/circular_dependency_orchestrator/src/vds_circular_dependency_orchestrator/cli.py +0 -904
  946. package/tools/vds-scripts/circular_dependency_orchestrator/tests/__init__.py +0 -0
  947. package/tools/vds-scripts/circular_dependency_orchestrator/tests/unit/__init__.py +0 -0
  948. package/tools/vds-scripts/circular_dependency_orchestrator/tests/unit/test_cli.py +0 -354
  949. package/tools/vds-scripts/coverage.json +0 -1
  950. package/tools/vds-scripts/create_pr.py +0 -57
  951. package/tools/vds-scripts/diagram_generator/README.md +0 -663
  952. package/tools/vds-scripts/diagram_generator/ci_validate.sh +0 -16
  953. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-component.png +0 -0
  954. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-component.puml +0 -23
  955. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-sequence.png +0 -0
  956. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-sequence.puml +0 -21
  957. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-usecase.png +0 -0
  958. package/tools/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-usecase.puml +0 -14
  959. package/tools/vds-scripts/diagram_generator/examples/github-actions-validate.yml +0 -39
  960. package/tools/vds-scripts/diagram_generator/generate_all_diagrams.py +0 -827
  961. package/tools/vds-scripts/diagram_generator/generate_insurance_c4_diagrams.py +0 -261
  962. package/tools/vds-scripts/diagram_generator/generate_insurance_c4_quick.py +0 -486
  963. package/tools/vds-scripts/diagram_generator/pyproject.toml +0 -28
  964. package/tools/vds-scripts/diagram_generator/render_png.py +0 -59
  965. package/tools/vds-scripts/diagram_generator/src/vds_diagram_generator/__init__.py +0 -3
  966. package/tools/vds-scripts/diagram_generator/src/vds_diagram_generator/cli.py +0 -50
  967. package/tools/vds-scripts/diagram_generator/test_c4_hierarchical.py +0 -142
  968. package/tools/vds-scripts/diagram_generator/test_c4_quick.py +0 -131
  969. package/tools/vds-scripts/diagram_generator/tests/__init__.py +0 -0
  970. package/tools/vds-scripts/diagram_generator/tests/test_analyzer_completeness.py +0 -260
  971. package/tools/vds-scripts/diagram_generator/tests/test_c4_syntax_correctness.py +0 -138
  972. package/tools/vds-scripts/diagram_generator/tests/test_component_coverage.py +0 -182
  973. package/tools/vds-scripts/diagram_generator/tests/test_mermaid_output.py +0 -80
  974. package/tools/vds-scripts/diagram_generator/tests/test_png_generation.py +0 -112
  975. package/tools/vds-scripts/diagram_generator/tests/test_scenario_templates.py +0 -15
  976. package/tools/vds-scripts/diagram_generator/tests/test_sequence_accuracy.py +0 -93
  977. package/tools/vds-scripts/diagram_generator/tests/test_structurizr_export.py +0 -177
  978. package/tools/vds-scripts/diagram_generator/tests/test_style_consistency.py +0 -174
  979. package/tools/vds-scripts/diagram_generator/tests/test_usecase_generator.py +0 -201
  980. package/tools/vds-scripts/diagram_generator/tests/test_usecase_integration.py +0 -124
  981. package/tools/vds-scripts/docker/compose.phase2-verification.yml +0 -31
  982. package/tools/vds-scripts/docker-compose.openapi-validator.yml +0 -14
  983. package/tools/vds-scripts/excel_orchestrator/README.md +0 -288
  984. package/tools/vds-scripts/excel_orchestrator/RESEARCH_BASED_UPDATES_REPORT.md +0 -261
  985. package/tools/vds-scripts/excel_orchestrator/add_essential_missing_effort.py +0 -255
  986. package/tools/vds-scripts/excel_orchestrator/adjust_effort_complexity.py +0 -184
  987. package/tools/vds-scripts/excel_orchestrator/brd_analysis_and_task_breakdown.py +0 -632
  988. package/tools/vds-scripts/excel_orchestrator/brd_analysis_comprehensive.py +0 -1029
  989. package/tools/vds-scripts/excel_orchestrator/check_overlaps_and_brd_coverage.py +0 -570
  990. package/tools/vds-scripts/excel_orchestrator/clean_remarks_column.py +0 -127
  991. package/tools/vds-scripts/excel_orchestrator/comprehensive_brd_check.py +0 -322
  992. package/tools/vds-scripts/excel_orchestrator/create_buffered_summary.py +0 -119
  993. package/tools/vds-scripts/excel_orchestrator/create_service_totals_sheet.py +0 -118
  994. package/tools/vds-scripts/excel_orchestrator/examples/basic_operations.py +0 -85
  995. package/tools/vds-scripts/excel_orchestrator/expand_all_tasks.py +0 -341
  996. package/tools/vds-scripts/excel_orchestrator/expand_tasks.py +0 -304
  997. package/tools/vds-scripts/excel_orchestrator/fill_brd_references.py +0 -347
  998. package/tools/vds-scripts/excel_orchestrator/fill_remarks_and_colors.py +0 -132
  999. package/tools/vds-scripts/excel_orchestrator/finalize_brd_and_cleanup.py +0 -295
  1000. package/tools/vds-scripts/excel_orchestrator/finalize_brd_coverage.py +0 -327
  1001. package/tools/vds-scripts/excel_orchestrator/fix_all_formulas.py +0 -99
  1002. package/tools/vds-scripts/excel_orchestrator/fix_detail_presentation.py +0 -113
  1003. package/tools/vds-scripts/excel_orchestrator/fix_presentation_and_effort.py +0 -116
  1004. package/tools/vds-scripts/excel_orchestrator/fix_presentation_consistency.py +0 -231
  1005. package/tools/vds-scripts/excel_orchestrator/fix_remarks_matching.py +0 -179
  1006. package/tools/vds-scripts/excel_orchestrator/group_tasks_by_service_id.py +0 -210
  1007. package/tools/vds-scripts/excel_orchestrator/increase_brd_coverage.py +0 -497
  1008. package/tools/vds-scripts/excel_orchestrator/increase_effort_complexity.py +0 -155
  1009. package/tools/vds-scripts/excel_orchestrator/organize_and_deduplicate.py +0 -273
  1010. package/tools/vds-scripts/excel_orchestrator/pyproject.toml +0 -64
  1011. package/tools/vds-scripts/excel_orchestrator/rebuild_all_formulas.py +0 -146
  1012. package/tools/vds-scripts/excel_orchestrator/remove_base_multiplier_and_check_duplicates.py +0 -310
  1013. package/tools/vds-scripts/excel_orchestrator/remove_duplicate_brd_tasks.py +0 -137
  1014. package/tools/vds-scripts/excel_orchestrator/research_based_updates.py +0 -457
  1015. package/tools/vds-scripts/excel_orchestrator/restore_e_values.py +0 -172
  1016. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/__init__.py +0 -5
  1017. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/cli.py +0 -746
  1018. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/config.py +0 -74
  1019. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/converters.py +0 -226
  1020. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/errors.py +0 -88
  1021. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/excel_client.py +0 -443
  1022. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/formatters.py +0 -211
  1023. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/logging.py +0 -57
  1024. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/source_contract.py +0 -29
  1025. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/target_state_status.py +0 -837
  1026. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/ulnc_alignment.py +0 -1291
  1027. package/tools/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/validators.py +0 -164
  1028. package/tools/vds-scripts/excel_orchestrator/sync_detail_and_total_sheets.py +0 -211
  1029. package/tools/vds-scripts/excel_orchestrator/tests/__init__.py +0 -1
  1030. package/tools/vds-scripts/excel_orchestrator/tests/conftest.py +0 -36
  1031. package/tools/vds-scripts/excel_orchestrator/tests/test_cli.py +0 -383
  1032. package/tools/vds-scripts/excel_orchestrator/tests/test_excel_client.py +0 -129
  1033. package/tools/vds-scripts/excel_orchestrator/tests/test_ulnc_alignment.py +0 -373
  1034. package/tools/vds-scripts/excel_orchestrator/tests/test_validators.py +0 -64
  1035. package/tools/vds-scripts/excel_orchestrator/update_api_database_effort.py +0 -261
  1036. package/tools/vds-scripts/excel_orchestrator/update_buffers_inline.py +0 -115
  1037. package/tools/vds-scripts/excel_orchestrator/update_complex_services_and_add_new.py +0 -336
  1038. package/tools/vds-scripts/excel_orchestrator/update_responsibility_and_fix_rows.py +0 -208
  1039. package/tools/vds-scripts/excel_orchestrator/update_task_breakdown_vietnamese.py +0 -309
  1040. package/tools/vds-scripts/excel_orchestrator/update_vietnamese_and_responsibility.py +0 -415
  1041. package/tools/vds-scripts/excel_orchestrator/verify_brd_coverage_comprehensive.py +0 -401
  1042. package/tools/vds-scripts/hexagonal_orchestrator/README.md +0 -530
  1043. package/tools/vds-scripts/hexagonal_orchestrator/pyproject.toml +0 -48
  1044. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/__init__.py +0 -39
  1045. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/analyzers/__init__.py +0 -19
  1046. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/analyzers/base.py +0 -95
  1047. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/analyzers/fallback.py +0 -614
  1048. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/analyzers/java.py +0 -372
  1049. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/analyzers/python.py +0 -437
  1050. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/cache.py +0 -331
  1051. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/classifier.py +0 -263
  1052. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/cli.py +0 -554
  1053. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/config.py +0 -577
  1054. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/models.py +0 -159
  1055. package/tools/vds-scripts/hexagonal_orchestrator/src/vds_hexagonal_orchestrator/profiler.py +0 -451
  1056. package/tools/vds-scripts/hexagonal_orchestrator/test-config.yaml +0 -38
  1057. package/tools/vds-scripts/hexagonal_orchestrator/tests/__init__.py +0 -1
  1058. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/__init__.py +0 -1
  1059. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/adapter/driven/persistence/InMemoryUserRepository.java +0 -62
  1060. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/adapter/driving/api/UserController.java +0 -101
  1061. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/application/port/EmailService.java +0 -33
  1062. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/application/port/UserRepository.java +0 -45
  1063. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/application/usecase/CreateUser.java +0 -58
  1064. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/domain/entity/Email.java +0 -80
  1065. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-compliant/domain/entity/User.java +0 -98
  1066. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-noncompliant/domain/User.java +0 -64
  1067. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-with-frameworks/domain/Menu.java +0 -13
  1068. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/java-with-frameworks/domain/Product.java +0 -16
  1069. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/__init__.py +0 -1
  1070. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/application/__init__.py +0 -1
  1071. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/application/ports/__init__.py +0 -1
  1072. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/application/ports/email_service.py +0 -60
  1073. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/application/ports/user_repository.py +0 -78
  1074. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/domain/__init__.py +0 -1
  1075. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/domain/entities/__init__.py +0 -1
  1076. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/domain/entities/user.py +0 -56
  1077. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/domain/value_objects/__init__.py +0 -1
  1078. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-compliant/domain/value_objects/email.py +0 -63
  1079. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-noncompliant/application/user_service.py +0 -1837
  1080. package/tools/vds-scripts/hexagonal_orchestrator/tests/fixtures/python-noncompliant/domain/user.py +0 -43
  1081. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_cache.py +0 -458
  1082. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_cli_integration.py +0 -942
  1083. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_cli_unit.py +0 -557
  1084. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_cross_repo_pollution.py +0 -275
  1085. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_foundation.py +0 -129
  1086. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_integration.py +0 -1524
  1087. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_java_analyzer.py +0 -642
  1088. package/tools/vds-scripts/hexagonal_orchestrator/tests/test_timing_unit.py +0 -60
  1089. package/tools/vds-scripts/intellij_orchestrator/README.md +0 -55
  1090. package/tools/vds-scripts/intellij_orchestrator/pyproject.toml +0 -64
  1091. package/tools/vds-scripts/intellij_orchestrator/src/vds_intellij_orchestrator/__init__.py +0 -17
  1092. package/tools/vds-scripts/intellij_orchestrator/src/vds_intellij_orchestrator/cli.py +0 -210
  1093. package/tools/vds-scripts/intellij_orchestrator/src/vds_intellij_orchestrator/core.py +0 -260
  1094. package/tools/vds-scripts/intellij_orchestrator/tests/__init__.py +0 -1
  1095. package/tools/vds-scripts/intellij_orchestrator/tests/test_cli.py +0 -112
  1096. package/tools/vds-scripts/intellij_orchestrator/tests/test_core.py +0 -83
  1097. package/tools/vds-scripts/links_orchestrator/README.md +0 -63
  1098. package/tools/vds-scripts/links_orchestrator/pyproject.toml +0 -64
  1099. package/tools/vds-scripts/links_orchestrator/src/vds_links_orchestrator/__init__.py +0 -10
  1100. package/tools/vds-scripts/links_orchestrator/src/vds_links_orchestrator/cli.py +0 -254
  1101. package/tools/vds-scripts/links_orchestrator/src/vds_links_orchestrator/validator.py +0 -244
  1102. package/tools/vds-scripts/links_orchestrator/tests/__init__.py +0 -0
  1103. package/tools/vds-scripts/links_orchestrator/tests/test_cli.py +0 -128
  1104. package/tools/vds-scripts/links_orchestrator/tests/test_validator.py +0 -76
  1105. package/tools/vds-scripts/lsp_orchestrator/.dockerignore +0 -69
  1106. package/tools/vds-scripts/lsp_orchestrator/ARCHITECTURE.md +0 -383
  1107. package/tools/vds-scripts/lsp_orchestrator/CODE_QUALITY_IMPROVEMENTS.md +0 -196
  1108. package/tools/vds-scripts/lsp_orchestrator/COMMANDS.md +0 -870
  1109. package/tools/vds-scripts/lsp_orchestrator/Dockerfile +0 -59
  1110. package/tools/vds-scripts/lsp_orchestrator/IMPLEMENTATION_SUMMARY.md +0 -490
  1111. package/tools/vds-scripts/lsp_orchestrator/LSP_ISSUES_AND_FINDINGS.md +0 -380
  1112. package/tools/vds-scripts/lsp_orchestrator/README.md +0 -616
  1113. package/tools/vds-scripts/lsp_orchestrator/SETUP.md +0 -143
  1114. package/tools/vds-scripts/lsp_orchestrator/TEST_COVERAGE_SUMMARY.md +0 -255
  1115. package/tools/vds-scripts/lsp_orchestrator/VERIFICATION_CHECKLIST.md +0 -814
  1116. package/tools/vds-scripts/lsp_orchestrator/docker-compose.yml +0 -102
  1117. package/tools/vds-scripts/lsp_orchestrator/docs/FOR_LLMS.md +0 -401
  1118. package/tools/vds-scripts/lsp_orchestrator/docs/explanation/lsp-response-matching.md +0 -79
  1119. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/automate-with-json.md +0 -159
  1120. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/docker-mode.md +0 -256
  1121. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/navigate-code.md +0 -116
  1122. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/parallel-processing.md +0 -179
  1123. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/project-tool-detection.md +0 -320
  1124. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/type-check-code.md +0 -46
  1125. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/use-daemon-mode.md +0 -78
  1126. package/tools/vds-scripts/lsp_orchestrator/docs/how-to-guides/wsl2-optimization.md +0 -227
  1127. package/tools/vds-scripts/lsp_orchestrator/docs/index.md +0 -88
  1128. package/tools/vds-scripts/lsp_orchestrator/docs/operator-hover-definition.md +0 -143
  1129. package/tools/vds-scripts/lsp_orchestrator/docs/reference/commands.md +0 -581
  1130. package/tools/vds-scripts/lsp_orchestrator/docs/reference/configuration.md +0 -422
  1131. package/tools/vds-scripts/lsp_orchestrator/docs/tutorials/00-quick-start.md +0 -169
  1132. package/tools/vds-scripts/lsp_orchestrator/pyproject.toml +0 -63
  1133. package/tools/vds-scripts/lsp_orchestrator/src/test_file.py +0 -5
  1134. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/__init__.py +0 -3
  1135. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/aggregator.py +0 -340
  1136. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/basedpyright_runner.py +0 -167
  1137. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/cli.py +0 -3370
  1138. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/code_actions.py +0 -79
  1139. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/core.py +0 -3295
  1140. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/daemon_client.py +0 -672
  1141. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/daemon_manager.py +0 -577
  1142. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/daemon_server.py +0 -1040
  1143. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/detectors/__init__.py +0 -9
  1144. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/detectors/project_detector.py +0 -537
  1145. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/formatters.py +0 -141
  1146. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/ipc_protocol.py +0 -225
  1147. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/lsp_client.py +0 -957
  1148. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/lsp_router.py +0 -335
  1149. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/mcp_server.py +0 -181
  1150. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/models/__init__.py +0 -201
  1151. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/models/project_detector.py +0 -646
  1152. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/models/project_tools.py +0 -114
  1153. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/models.py +0 -399
  1154. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/mypy_runner.py +0 -209
  1155. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/protocols.py +0 -52
  1156. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/ruff_lsp_client.py +0 -109
  1157. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/ruff_runner.py +0 -44
  1158. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/utils.py +0 -959
  1159. package/tools/vds-scripts/lsp_orchestrator/src/vds_lsp_orchestrator/workspace_indexer.py +0 -1037
  1160. package/tools/vds-scripts/lsp_orchestrator/test_workspace_lsp.py +0 -6
  1161. package/tools/vds-scripts/lsp_orchestrator/tests/__init__.py +0 -1
  1162. package/tools/vds-scripts/lsp_orchestrator/tests/conftest.py +0 -6
  1163. package/tools/vds-scripts/lsp_orchestrator/tests/test_aggregator.py +0 -59
  1164. package/tools/vds-scripts/lsp_orchestrator/tests/test_cli.py +0 -111
  1165. package/tools/vds-scripts/lsp_orchestrator/tests/test_detect_tools_command.py +0 -186
  1166. package/tools/vds-scripts/lsp_orchestrator/tests/test_formatter_linter_detection.py +0 -519
  1167. package/tools/vds-scripts/lsp_orchestrator/tests/test_integration_phase9_10_11.py +0 -367
  1168. package/tools/vds-scripts/lsp_orchestrator/tests/test_mypy_runner.py +0 -482
  1169. package/tools/vds-scripts/lsp_orchestrator/tests/test_package_manager_detection.py +0 -399
  1170. package/tools/vds-scripts/lsp_orchestrator/tests/test_phase10.py +0 -389
  1171. package/tools/vds-scripts/lsp_orchestrator/tests/test_phase11.py +0 -327
  1172. package/tools/vds-scripts/lsp_orchestrator/tests/test_phase12_integration.py +0 -634
  1173. package/tools/vds-scripts/lsp_orchestrator/tests/test_phase9.py +0 -196
  1174. package/tools/vds-scripts/lsp_orchestrator/tests/test_project_detector.py +0 -377
  1175. package/tools/vds-scripts/lsp_orchestrator/tests/test_test_runner_detection.py +0 -549
  1176. package/tools/vds-scripts/lsp_orchestrator/tests/test_type_checker_routing.py +0 -362
  1177. package/tools/vds-scripts/lsp_orchestrator/tests/test_workspace_indexer.py +0 -144
  1178. package/tools/vds-scripts/markdown_orchestrator/README.md +0 -72
  1179. package/tools/vds-scripts/markdown_orchestrator/pyproject.toml +0 -39
  1180. package/tools/vds-scripts/markdown_orchestrator/src/vds_markdown_orchestrator/__init__.py +0 -5
  1181. package/tools/vds-scripts/markdown_orchestrator/src/vds_markdown_orchestrator/cli.py +0 -102
  1182. package/tools/vds-scripts/multi_agent_orchestrator/Dockerfile +0 -65
  1183. package/tools/vds-scripts/multi_agent_orchestrator/README.md +0 -306
  1184. package/tools/vds-scripts/multi_agent_orchestrator/postman/README.md +0 -264
  1185. package/tools/vds-scripts/multi_agent_orchestrator/postman/TEST_RESULTS_SUMMARY.md +0 -197
  1186. package/tools/vds-scripts/multi_agent_orchestrator/postman/VDS-Multi-Agent-Orchestrator-API.postman_collection.json +0 -1010
  1187. package/tools/vds-scripts/multi_agent_orchestrator/postman/environments/local-development.postman_environment.json +0 -55
  1188. package/tools/vds-scripts/multi_agent_orchestrator/postman/test-results.json +0 -24146
  1189. package/tools/vds-scripts/multi_agent_orchestrator/pyproject.toml +0 -63
  1190. package/tools/vds-scripts/multi_agent_orchestrator/run_api.py +0 -9
  1191. package/tools/vds-scripts/multi_agent_orchestrator/run_mock_api.py +0 -9
  1192. package/tools/vds-scripts/multi_agent_orchestrator/simple_test.py +0 -53
  1193. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/__init__.py +0 -25
  1194. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/agent_pool.py +0 -433
  1195. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/api/__init__.py +0 -5
  1196. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/api/main.py +0 -722
  1197. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/api/mock_main.py +0 -812
  1198. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/change_log.py +0 -515
  1199. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/cli.py +0 -424
  1200. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/config.py +0 -220
  1201. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/conflict_resolver.py +0 -462
  1202. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/coordinator.py +0 -627
  1203. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/models.py +0 -389
  1204. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/progress_dashboard.py +0 -380
  1205. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/redis_client.py +0 -245
  1206. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/scheduler_subscriber.py +0 -272
  1207. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/task_manager.py +0 -536
  1208. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/task_tracking.py +0 -550
  1209. package/tools/vds-scripts/multi_agent_orchestrator/src/vds_multi_agent_orchestrator/vds_ai_memory_client.py +0 -352
  1210. package/tools/vds-scripts/multi_agent_orchestrator/test_complete_system.py +0 -149
  1211. package/tools/vds-scripts/multi_agent_orchestrator/test_infrastructure_only.py +0 -194
  1212. package/tools/vds-scripts/multi_agent_orchestrator/test_integration.py +0 -108
  1213. package/tools/vds-scripts/multi_agent_orchestrator/tests/__init__.py +0 -1
  1214. package/tools/vds-scripts/multi_agent_orchestrator/tests/test_agent_registration_credential_validator.py +0 -223
  1215. package/tools/vds-scripts/multi_agent_orchestrator/tests/test_config.py +0 -210
  1216. package/tools/vds-scripts/multi_agent_orchestrator/tests/test_models.py +0 -195
  1217. package/tools/vds-scripts/multi_agent_orchestrator/tests/test_w9_agent_routes.py +0 -321
  1218. package/tools/vds-scripts/openapi_orchestrator/README.md +0 -197
  1219. package/tools/vds-scripts/openapi_orchestrator/pyproject.toml +0 -106
  1220. package/tools/vds-scripts/openapi_orchestrator/src/vds_openapi_orchestrator/__init__.py +0 -29
  1221. package/tools/vds-scripts/openapi_orchestrator/src/vds_openapi_orchestrator/cli.py +0 -345
  1222. package/tools/vds-scripts/openapi_orchestrator/src/vds_openapi_orchestrator/full_validator.py +0 -183
  1223. package/tools/vds-scripts/openapi_orchestrator/src/vds_openapi_orchestrator/spec_validator.py +0 -197
  1224. package/tools/vds-scripts/openapi_orchestrator/tests/__init__.py +0 -1
  1225. package/tools/vds-scripts/openapi_orchestrator/tests/test_cli.py +0 -234
  1226. package/tools/vds-scripts/openapi_orchestrator/tests/test_full_validator.py +0 -203
  1227. package/tools/vds-scripts/openapi_orchestrator/tests/test_spec_validator.py +0 -295
  1228. package/tools/vds-scripts/pdf_orchestrator/.dockerignore +0 -93
  1229. package/tools/vds-scripts/pdf_orchestrator/.env.example +0 -40
  1230. package/tools/vds-scripts/pdf_orchestrator/.ruff_rules.py +0 -350
  1231. package/tools/vds-scripts/pdf_orchestrator/.yamllint.yml +0 -43
  1232. package/tools/vds-scripts/pdf_orchestrator/DEVELOPMENT_PLAN.md +0 -80
  1233. package/tools/vds-scripts/pdf_orchestrator/Dockerfile +0 -87
  1234. package/tools/vds-scripts/pdf_orchestrator/README.md +0 -608
  1235. package/tools/vds-scripts/pdf_orchestrator/cli_verification_test/test.md +0 -6
  1236. package/tools/vds-scripts/pdf_orchestrator/cli_verification_test/test.pdf +0 -0
  1237. package/tools/vds-scripts/pdf_orchestrator/config/alertmanager.yml +0 -83
  1238. package/tools/vds-scripts/pdf_orchestrator/config/prometheus.prod.yml +0 -98
  1239. package/tools/vds-scripts/pdf_orchestrator/config/prometheus.yml +0 -40
  1240. package/tools/vds-scripts/pdf_orchestrator/config/redis.conf +0 -78
  1241. package/tools/vds-scripts/pdf_orchestrator/docs/COMPETITIVE_ANALYSIS_REPORT.md +0 -309
  1242. package/tools/vds-scripts/pdf_orchestrator/docs/FEATURES_GUIDE.md +0 -518
  1243. package/tools/vds-scripts/pdf_orchestrator/docs/MULTI_USER_DEPLOYMENT_GUIDE.md +0 -615
  1244. package/tools/vds-scripts/pdf_orchestrator/docs/USER_GUIDE.md +0 -829
  1245. package/tools/vds-scripts/pdf_orchestrator/pyproject.toml +0 -87
  1246. package/tools/vds-scripts/pdf_orchestrator/pytest.ini +0 -71
  1247. package/tools/vds-scripts/pdf_orchestrator/ruff.toml +0 -6
  1248. package/tools/vds-scripts/pdf_orchestrator/scripts/debug_security_report.py +0 -59
  1249. package/tools/vds-scripts/pdf_orchestrator/scripts/demo_library_selector.py +0 -109
  1250. package/tools/vds-scripts/pdf_orchestrator/scripts/generate_project_stats.py +0 -52
  1251. package/tools/vds-scripts/pdf_orchestrator/scripts/generate_styled_pdf.py +0 -95
  1252. package/tools/vds-scripts/pdf_orchestrator/scripts/migrate_render_pdfs.py +0 -285
  1253. package/tools/vds-scripts/pdf_orchestrator/scripts/setup_team.bat +0 -283
  1254. package/tools/vds-scripts/pdf_orchestrator/scripts/setup_team.sh +0 -324
  1255. package/tools/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/__init__.py +0 -5
  1256. package/tools/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/cli.py +0 -542
  1257. package/tools/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/config.py +0 -33
  1258. package/tools/vds-scripts/pdf_orchestrator/tests/README.md +0 -650
  1259. package/tools/vds-scripts/pdf_orchestrator/tests/__init__.py +0 -0
  1260. package/tools/vds-scripts/pdf_orchestrator/tests/conftest.py +0 -520
  1261. package/tools/vds-scripts/pdf_orchestrator/tests/requirements.txt +0 -51
  1262. package/tools/vds-scripts/pdf_orchestrator/tests/run_tests.py +0 -659
  1263. package/tools/vds-scripts/pdf_orchestrator/tests/test_config.py +0 -36
  1264. package/tools/vds-scripts/progress_report_orchestrator/Dockerfile +0 -77
  1265. package/tools/vds-scripts/progress_report_orchestrator/README.md +0 -39
  1266. package/tools/vds-scripts/progress_report_orchestrator/alembic/env.py +0 -42
  1267. package/tools/vds-scripts/progress_report_orchestrator/alembic/script.py.mako +0 -28
  1268. package/tools/vds-scripts/progress_report_orchestrator/alembic/versions/0001_initial_progress_schema.py +0 -180
  1269. package/tools/vds-scripts/progress_report_orchestrator/alembic.ini +0 -67
  1270. package/tools/vds-scripts/progress_report_orchestrator/pyproject.toml +0 -67
  1271. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/__init__.py +0 -3
  1272. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/analyzers/__init__.py +0 -1
  1273. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/analyzers/endpoint_scanner.py +0 -238
  1274. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/analyzers/git_activity.py +0 -159
  1275. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/analyzers/hexagonal.py +0 -100
  1276. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/analyzers/test_scanner.py +0 -136
  1277. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/cli.py +0 -743
  1278. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/config.py +0 -50
  1279. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/db/__init__.py +0 -12
  1280. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/db/alembic_filters.py +0 -64
  1281. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/memory.py +0 -82
  1282. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/models/__init__.py +0 -1
  1283. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/models/analysis.py +0 -84
  1284. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/models/report.py +0 -117
  1285. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/models/topology.py +0 -101
  1286. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/parsers/__init__.py +0 -1
  1287. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/parsers/kg_parser.py +0 -252
  1288. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/parsers/uc_reader.py +0 -159
  1289. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/__init__.py +0 -1
  1290. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/concurrency.py +0 -39
  1291. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/llm_eval.py +0 -570
  1292. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/report.py +0 -1256
  1293. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/structural.py +0 -384
  1294. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/pipeline/sync.py +0 -143
  1295. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/recommendations/__init__.py +0 -5
  1296. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/recommendations/engine.py +0 -105
  1297. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/recommendations/templates.py +0 -236
  1298. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/scheduler_subscriber.py +0 -238
  1299. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/skills/README.md +0 -56
  1300. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/skills/__init__.py +0 -1
  1301. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/skills/srs-architecture-reviewer/SKILL.md +0 -67
  1302. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/skills/srs-endpoint-matcher/SKILL.md +0 -67
  1303. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/state/__init__.py +0 -1
  1304. package/tools/vds-scripts/progress_report_orchestrator/src/progress_report_orchestrator/state/schema.py +0 -625
  1305. package/tools/vds-scripts/progress_report_orchestrator/tests/__init__.py +0 -0
  1306. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/__init__.py +0 -0
  1307. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/.gitkeep +0 -0
  1308. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/__init__.py +0 -0
  1309. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/doc-dependencies.yaml +0 -79
  1310. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/fr-to-docs.yaml +0 -478
  1311. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/fr-to-services.yaml +0 -18
  1312. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/kg/registry.yaml +0 -346
  1313. package/tools/vds-scripts/progress_report_orchestrator/tests/fixtures/phase3_baseline_standard.md +0 -564
  1314. package/tools/vds-scripts/progress_report_orchestrator/tests/integration/__init__.py +0 -0
  1315. package/tools/vds-scripts/progress_report_orchestrator/tests/integration/test_checkpoint.py +0 -276
  1316. package/tools/vds-scripts/progress_report_orchestrator/tests/test_alembic_migrations.py +0 -265
  1317. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/__init__.py +0 -0
  1318. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_analyzers.py +0 -267
  1319. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_bounded_gather.py +0 -176
  1320. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_cli_phase_report.py +0 -119
  1321. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_delta.py +0 -169
  1322. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_error_handling.py +0 -150
  1323. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_gate_exit_codes.py +0 -230
  1324. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_git_activity.py +0 -215
  1325. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_kg_parser.py +0 -267
  1326. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_llm_autodetect.py +0 -183
  1327. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_llm_eval.py +0 -529
  1328. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_memory_integration.py +0 -151
  1329. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_migration_contract.py +0 -254
  1330. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_mode_rendering.py +0 -576
  1331. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_models.py +0 -251
  1332. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_progress_llm_config.py +0 -67
  1333. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_recommendations.py +0 -480
  1334. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_report_enhancements.py +0 -415
  1335. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_resume_reload.py +0 -343
  1336. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_trend_regression.py +0 -294
  1337. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_uc_reader.py +0 -169
  1338. package/tools/vds-scripts/progress_report_orchestrator/tests/unit/test_valence_gap.py +0 -293
  1339. package/tools/vds-scripts/project-cycle-report.json +0 -14
  1340. package/tools/vds-scripts/project-dependency-graph.json +0 -11361
  1341. package/tools/vds-scripts/project-topology.json +0 -99
  1342. package/tools/vds-scripts/public_interface_boundary_orchestrator/pyproject.toml +0 -18
  1343. package/tools/vds-scripts/public_interface_boundary_orchestrator/src/vds_public_interface_boundary_orchestrator/__init__.py +0 -0
  1344. package/tools/vds-scripts/public_interface_boundary_orchestrator/src/vds_public_interface_boundary_orchestrator/cli.py +0 -232
  1345. package/tools/vds-scripts/public_interface_boundary_orchestrator/tests/__init__.py +0 -0
  1346. package/tools/vds-scripts/public_interface_boundary_orchestrator/tests/test_cli.py +0 -108
  1347. package/tools/vds-scripts/research_orchestrator/README.md +0 -68
  1348. package/tools/vds-scripts/research_orchestrator/py.typed +0 -0
  1349. package/tools/vds-scripts/research_orchestrator/pyproject.toml +0 -95
  1350. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/__init__.py +0 -3
  1351. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/_env.py +0 -11
  1352. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/cli.py +0 -335
  1353. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/config.py +0 -43
  1354. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/evidence/__init__.py +0 -0
  1355. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/evidence/models.py +0 -89
  1356. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/evidence/scoring.py +0 -102
  1357. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/exceptions.py +0 -78
  1358. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/http_client.py +0 -160
  1359. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/logging.py +0 -49
  1360. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/output/__init__.py +0 -0
  1361. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/output/formatters.py +0 -93
  1362. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/py.typed +0 -1
  1363. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/report/__init__.py +0 -0
  1364. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/report/build.py +0 -156
  1365. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/report/format.py +0 -147
  1366. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/tools/__init__.py +0 -0
  1367. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/tools/health.py +0 -66
  1368. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/tools/health_graph.py +0 -52
  1369. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/tools/registry.py +0 -127
  1370. package/tools/vds-scripts/research_orchestrator/src/vds_research_orchestrator/tools/search.py +0 -230
  1371. package/tools/vds-scripts/research_orchestrator/tests/__init__.py +0 -0
  1372. package/tools/vds-scripts/research_orchestrator/tests/conftest.py +0 -53
  1373. package/tools/vds-scripts/research_orchestrator/tests/test_cli.py +0 -222
  1374. package/tools/vds-scripts/research_orchestrator/tests/test_config.py +0 -23
  1375. package/tools/vds-scripts/research_orchestrator/tests/test_exceptions.py +0 -62
  1376. package/tools/vds-scripts/research_orchestrator/tests/test_formatters.py +0 -89
  1377. package/tools/vds-scripts/research_orchestrator/tests/test_graph_integration.py +0 -149
  1378. package/tools/vds-scripts/research_orchestrator/tests/test_http_client.py +0 -134
  1379. package/tools/vds-scripts/research_orchestrator/tests/test_report_build.py +0 -128
  1380. package/tools/vds-scripts/research_orchestrator/tests/test_report_format.py +0 -91
  1381. package/tools/vds-scripts/research_orchestrator/tests/test_scoring.py +0 -95
  1382. package/tools/vds-scripts/research_orchestrator/tests/vds_research_orchestrator/test_tools/__init__.py +0 -1
  1383. package/tools/vds-scripts/research_orchestrator/tests/vds_research_orchestrator/test_tools/test_health.py +0 -139
  1384. package/tools/vds-scripts/research_orchestrator/tests/vds_research_orchestrator/test_tools/test_registry.py +0 -135
  1385. package/tools/vds-scripts/research_orchestrator/tests/vds_research_orchestrator/test_tools/test_search.py +0 -238
  1386. package/tools/vds-scripts/run-history.json +0 -26
  1387. package/tools/vds-scripts/schema_converter/README.md +0 -109
  1388. package/tools/vds-scripts/schema_converter/pyproject.toml +0 -37
  1389. package/tools/vds-scripts/schema_converter/src/vds_schema_converter/__init__.py +0 -3
  1390. package/tools/vds-scripts/schema_converter/src/vds_schema_converter/cli.py +0 -50
  1391. package/tools/vds-scripts/schema_converter/tests/__init__.py +0 -0
  1392. package/tools/vds-scripts/schema_converter/tests/test_json_schema_generator.py +0 -115
  1393. package/tools/vds-scripts/schema_converter/tests/test_mermaid_generator.py +0 -112
  1394. package/tools/vds-scripts/schema_converter/tests/test_parser.py +0 -111
  1395. package/tools/vds-scripts/schema_converter/tests/test_plantuml_generator.py +0 -112
  1396. package/tools/vds-scripts/schema_converter/tests/test_plantuml_validator.py +0 -69
  1397. package/tools/vds-scripts/schema_converter/tests/test_prisma_generator.py +0 -113
  1398. package/tools/vds-scripts/schema_converter/tests/test_sql_generator.py +0 -138
  1399. package/tools/vds-scripts/schema_converter/tests/test_typeorm_generator.py +0 -110
  1400. package/tools/vds-scripts/schema_converter/tests/test_validators.py +0 -96
  1401. package/tools/vds-scripts/spec_orchestrator/README.md +0 -13
  1402. package/tools/vds-scripts/spec_orchestrator/pyproject.toml +0 -40
  1403. package/tools/vds-scripts/spec_orchestrator/src/vds_spec_orchestrator/__init__.py +0 -5
  1404. package/tools/vds-scripts/spec_orchestrator/src/vds_spec_orchestrator/cli.py +0 -162
  1405. package/tools/vds-scripts/spec_orchestrator/src/vds_spec_orchestrator/core.py +0 -575
  1406. package/tools/vds-scripts/spec_orchestrator/src/vds_spec_orchestrator/sync.py +0 -306
  1407. package/tools/vds-scripts/spec_orchestrator/tests/__init__.py +0 -0
  1408. package/tools/vds-scripts/spec_orchestrator/tests/test_frontmatter_drift.py +0 -243
  1409. package/tools/vds-scripts/spec_orchestrator/tests/test_sync.py +0 -342
  1410. package/tools/vds-scripts/structure_orchestrator/README.md +0 -60
  1411. package/tools/vds-scripts/structure_orchestrator/pyproject.toml +0 -103
  1412. package/tools/vds-scripts/structure_orchestrator/src/vds_structure_orchestrator/__init__.py +0 -13
  1413. package/tools/vds-scripts/structure_orchestrator/src/vds_structure_orchestrator/cli.py +0 -308
  1414. package/tools/vds-scripts/structure_orchestrator/src/vds_structure_orchestrator/validator.py +0 -257
  1415. package/tools/vds-scripts/structure_orchestrator/tests/__init__.py +0 -0
  1416. package/tools/vds-scripts/structure_orchestrator/tests/test_cli.py +0 -161
  1417. package/tools/vds-scripts/structure_orchestrator/tests/test_helpers.py +0 -115
  1418. package/tools/vds-scripts/structure_orchestrator/tests/test_validator.py +0 -104
  1419. package/tools/vds-scripts/task_orchestrator/README.md +0 -50
  1420. package/tools/vds-scripts/task_orchestrator/__init__.py +0 -18
  1421. package/tools/vds-scripts/task_orchestrator/pyproject.toml +0 -43
  1422. package/tools/vds-scripts/task_orchestrator/scripts/run_excel_sync.py +0 -36
  1423. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/__init__.py +0 -13
  1424. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/audit.py +0 -134
  1425. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/cli.py +0 -127
  1426. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/debug.py +0 -133
  1427. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/normalize.py +0 -113
  1428. package/tools/vds-scripts/task_orchestrator/src/vds_task_orchestrator/refine.py +0 -201
  1429. package/tools/vds-scripts/task_orchestrator/tests/__init__.py +0 -0
  1430. package/tools/vds-scripts/task_orchestrator/tests/test_task_orchestrator.py +0 -84
  1431. package/tools/vds-scripts/temp_query_projects.py +0 -2
  1432. package/tools/vds-scripts/test_small.md +0 -1
  1433. package/tools/vds-scripts/text_utils_orchestrator/pyproject.toml +0 -20
  1434. package/tools/vds-scripts/text_utils_orchestrator/src/vds_text_utils/__init__.py +0 -7
  1435. package/tools/vds-scripts/text_utils_orchestrator/src/vds_text_utils/i18n.py +0 -143
  1436. package/tools/vds-scripts/text_utils_orchestrator/tests/__init__.py +0 -0
  1437. package/tools/vds-scripts/text_utils_orchestrator/tests/test_i18n.py +0 -53
  1438. package/tools/vds-scripts/upgrade_major.py +0 -61
  1439. package/tools/vds-scripts/upgrade_major_v2.py +0 -64
  1440. package/tools/vds-scripts/verify_violations.py +0 -57
  1441. package/tools/vds-scripts/workflow-summary.json +0 -325
  1442. package/tools/vds-scripts/workflow-summary.md +0 -8
@@ -1,3822 +0,0 @@
1
- """Centralized tool registry for tool-first row analysis (Phase 61).
2
-
3
- Provides strict typed schemas for tool requests/responses and a lightweight
4
- registry that can be extended with real tool handlers incrementally.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import json
10
- import os
11
- import re
12
- import subprocess
13
- import unicodedata
14
- from collections.abc import Callable, Mapping
15
- from enum import StrEnum
16
- from pathlib import Path
17
- from typing import Any, Literal, cast
18
- from urllib.parse import parse_qs, urlparse
19
-
20
- import structlog
21
- from pydantic import AliasChoices, BaseModel, ConfigDict, Field, ValidationError, field_validator
22
- from vds_cli_common.paths import get_vds_cache_root
23
-
24
- from vds_audit_orchestrator.engine.project_topology import RepoRole, classify_repo_role
25
- from vds_audit_orchestrator.evidence.code_pack import CodeEvidencePack, CodePackBuilder
26
- from vds_audit_orchestrator.evidence.embedding_client import OllamaEmbeddingClient
27
- from vds_audit_orchestrator.evidence.query_service import StateBackedEvidenceQueryAdapter
28
- from vds_audit_orchestrator.state.store import PostgresStateStore
29
-
30
- _log = structlog.get_logger(__name__)
31
-
32
-
33
- class _StrictModel(BaseModel):
34
- """Strict base model for tool IO payloads."""
35
-
36
- model_config = ConfigDict(extra="forbid", strict=True)
37
-
38
-
39
- class ToolName(StrEnum):
40
- """Supported tool names for Phase 61 scaffolding."""
41
-
42
- SEARCH_DOCS = "search_docs"
43
- SEARCH_CODE = "search_code"
44
- READ_DOC_CHUNK = "read_doc_chunk"
45
- READ_CODE_FILE = "read_code_file"
46
- GET_ROW_CONTEXT = "get_row_context"
47
- RECORD_EVIDENCE_REFS = "record_evidence_refs"
48
- LIST_SKILLS = "list_skills"
49
- LOAD_SKILL = "load_skill"
50
- READ_SKILL_RESOURCE = "read_skill_resource"
51
- RUN_SKILL_SCRIPT = "run_skill_script"
52
- AST_GREP_CODE_SEARCH = "ast_grep_code_search"
53
-
54
-
55
- class SearchHit(_StrictModel):
56
- ref: str
57
- read_ref: str | None = None
58
- title: str | None = None
59
- score: float = Field(default=0.0, ge=0.0, le=1.0)
60
- excerpt: str | None = None
61
- chunk_id: str | None = None
62
- document_id: str | None = None
63
- page_id: str | None = None
64
- page_title: str | None = None
65
- space_key: str | None = None
66
- source_url: str | None = None
67
- source_type: str | None = None
68
- doc_class: str | None = None
69
-
70
-
71
- class EvidenceRef(_StrictModel):
72
- ref_type: str
73
- ref_value: str
74
- verified: bool = False
75
- line_range: tuple[int, int] | None = None
76
- page_id: str | None = None
77
- source_url: str | None = Field(default=None, validation_alias=AliasChoices("source_url", "source_uri"))
78
- page_title: str | None = None
79
- chunk_id: str | None = None
80
- excerpt: str | None = None
81
- verification_reason: str | None = None
82
- ref_hash: str | None = None
83
-
84
- @field_validator("line_range", mode="before")
85
- @classmethod
86
- def _coerce_line_range(cls, value: Any) -> Any:
87
- if value is None:
88
- return None
89
- if isinstance(value, list) and len(value) == 2:
90
- return (value[0], value[1])
91
- if isinstance(value, tuple) and len(value) == 2:
92
- return value
93
- if isinstance(value, str):
94
- match = re.match(r"^\s*(\d+)\s*[:,-]\s*(\d+)\s*$", value)
95
- if match:
96
- return (int(match.group(1)), int(match.group(2)))
97
- return value
98
-
99
-
100
- class SearchDocsInput(_StrictModel):
101
- query: str = Field(min_length=1)
102
- limit: int = Field(default=5, ge=1, le=50)
103
-
104
-
105
- class SearchDocsOutput(_StrictModel):
106
- hits: list[SearchHit] = Field(default_factory=list)
107
-
108
-
109
- class SearchCodeInput(_StrictModel):
110
- query: str = Field(min_length=1)
111
- limit: int = Field(default=5, ge=1, le=50)
112
- scope: Literal["code", "config", "lib", "all"] = Field(
113
- default="code",
114
- description="Evidence scope: 'code' for source files, 'config' for configuration files, 'lib' for shared libraries, 'all' for everything",
115
- )
116
- config_root_filter: str | None = Field(
117
- default=None,
118
- description="Optional config-root selector when scope is 'config' or 'all' (for example 'app-config')",
119
- )
120
- use_vector: bool = False
121
-
122
-
123
- class SearchCodeHit(_StrictModel):
124
- ref: str
125
- title: str | None = None
126
- score: float = Field(default=0.0, ge=0.0, le=1.0)
127
- excerpt: str | None = None
128
- source: Literal["code", "config", "lib"]
129
- retrieval_mode: Literal["lexical", "vector"] = "lexical"
130
-
131
-
132
- class SearchCodeOutput(_StrictModel):
133
- hits: list[SearchCodeHit] = Field(default_factory=list)
134
-
135
-
136
- class AstGrepHit(_StrictModel):
137
- ref: str
138
- line: int
139
- excerpt: str
140
- language: str | None = None
141
-
142
-
143
- class AstGrepCodeSearchInput(_StrictModel):
144
- pattern: str = Field(min_length=1)
145
- language: str | None = None
146
- include: str | None = None
147
- max_results: int = Field(default=50, ge=1, le=500)
148
-
149
-
150
- class AstGrepCodeSearchOutput(_StrictModel):
151
- hits: list[AstGrepHit] = Field(default_factory=list)
152
-
153
-
154
- class ReadDocChunkInput(_StrictModel):
155
- ref: str = Field(min_length=1)
156
- chunk_id: str | None = None
157
-
158
-
159
- class ReadDocChunkOutput(_StrictModel):
160
- ref: str
161
- chunk_id: str | None = None
162
- content: str = ""
163
- page_id: str | None = None
164
- page_title: str | None = None
165
- space_key: str | None = None
166
- source_url: str | None = None
167
- start_line: int | None = None
168
- end_line: int | None = None
169
-
170
-
171
- class ReadCodeFileInput(_StrictModel):
172
- path: str = Field(min_length=1)
173
- start_line: int | None = Field(default=None, ge=1)
174
- end_line: int | None = Field(default=None, ge=1)
175
- scope: Literal["code", "config", "lib", "all"] = Field(
176
- default="code",
177
- description="Evidence scope hint: indicates which evidence domain the file belongs to",
178
- )
179
- config_root_filter: str | None = Field(
180
- default=None,
181
- description="Optional config-root selector when reading config files (for example 'app-config')",
182
- )
183
-
184
-
185
- class ReadCodeFileOutput(_StrictModel):
186
- path: str
187
- content: str = ""
188
- start_line: int | None = None
189
- end_line: int | None = None
190
-
191
-
192
- class GetRowContextInput(_StrictModel):
193
- row_id: str = Field(min_length=1)
194
- check_id: str = Field(min_length=1)
195
- requirement_text: str = ""
196
- requirement_category: str | None = None
197
- detailed_guidance: str | None = None
198
- check_manual: bool = False
199
- requirement_interpretation: dict[str, Any] = Field(default_factory=dict)
200
- evidence_refs: list[str] = Field(default_factory=list)
201
-
202
-
203
- class GetRowContextOutput(_StrictModel):
204
- row_id: str
205
- context: dict[str, Any] = Field(default_factory=dict)
206
-
207
-
208
- class RecordEvidenceRefsInput(_StrictModel):
209
- row_id: str = Field(min_length=1)
210
- refs: list[EvidenceRef] = Field(default_factory=list)
211
-
212
-
213
- class RecordEvidenceRefsOutput(_StrictModel):
214
- row_id: str
215
- accepted_count: int = 0
216
- refs: list[EvidenceRef] = Field(default_factory=list)
217
-
218
-
219
- class SkillInfo(_StrictModel):
220
- name: str
221
- description: str | None = None
222
- trust_tier: str | None = None
223
- has_scripts: bool = False
224
- path: str
225
-
226
-
227
- class ListSkillsInput(_StrictModel):
228
- query: str = ""
229
- limit: int = Field(default=20, ge=1, le=100)
230
-
231
-
232
- class ListSkillsOutput(_StrictModel):
233
- skills: list[SkillInfo] = Field(default_factory=list)
234
-
235
-
236
- class LoadSkillInput(_StrictModel):
237
- name: str = Field(min_length=1, validation_alias=AliasChoices("name", "skill_name"))
238
-
239
-
240
- class LoadSkillOutput(_StrictModel):
241
- name: str
242
- found: bool = False
243
- resolved_name: str | None = None
244
- path: str | None = None
245
- description: str | None = None
246
- trust_tier: str | None = None
247
- has_scripts: bool = False
248
- resources: list[str] = Field(default_factory=list)
249
- scripts: list[str] = Field(default_factory=list)
250
- content_hash: str | None = None
251
- error: str | None = None
252
-
253
-
254
- class ReadSkillResourceInput(_StrictModel):
255
- name: str = Field(min_length=1, validation_alias=AliasChoices("name", "skill_name"))
256
- resource_path: str = Field(
257
- default="SKILL.md",
258
- min_length=1,
259
- validation_alias=AliasChoices("resource_path", "resource_name", "path"),
260
- )
261
- max_chars: int = Field(default=6000, ge=200, le=20000)
262
-
263
-
264
- class ReadSkillResourceOutput(_StrictModel):
265
- name: str
266
- resource_path: str
267
- success: bool = False
268
- content: str = ""
269
- ref: str | None = None
270
- error: str | None = None
271
- # P172-F (TSK-172.35): fallback telemetry — set when SKILL.md served instead of the
272
- # explicitly requested resource (e.g. references/row-analysis.md was absent).
273
- requested_resource_fallback: bool = False
274
- fallback_reason: str | None = None
275
-
276
-
277
- class RunSkillScriptInput(_StrictModel):
278
- name: str = Field(min_length=1, validation_alias=AliasChoices("name", "skill_name"))
279
- script_path: str = Field(min_length=1, validation_alias=AliasChoices("script_path", "script"))
280
- args: list[str] = Field(default_factory=list)
281
- timeout_seconds: int = Field(default=60, ge=1, le=600)
282
-
283
-
284
- class RunSkillScriptOutput(_StrictModel):
285
- name: str
286
- script_path: str
287
- success: bool = False
288
- stdout: str = ""
289
- stderr: str = ""
290
- returncode: int | None = None
291
- error: str | None = None
292
-
293
-
294
- class AstGrepPatternEntry(_StrictModel):
295
- pattern: str
296
- language: str
297
- description: str
298
- violation_category: str
299
-
300
-
301
- class ToolCallEnvelope(_StrictModel):
302
- """Common wrapper for validated tool invocations."""
303
-
304
- tool: ToolName
305
- payload: dict[str, Any] = Field(default_factory=dict)
306
-
307
-
308
- class ToolResponseEnvelope(_StrictModel):
309
- """Common wrapper for validated tool responses.
310
-
311
- Accepts both ToolName enum and plain str for compatibility with the
312
- core BoundedAgentLoop which passes tool names as strings.
313
- """
314
-
315
- tool: ToolName | str
316
- payload: dict[str, Any] = Field(default_factory=dict)
317
-
318
-
319
- ToolHandler = Callable[[Any], Any]
320
-
321
-
322
- class ToolExecutionError(RuntimeError):
323
- """Machine-readable runtime error for tool execution failures."""
324
-
325
- def __init__(self, code: str, message: str, *, details: dict[str, Any] | None = None) -> None:
326
- self.code = str(code).strip() or "tool_execution_error"
327
- self.message = str(message).strip() or "Tool execution failed"
328
- self.details = dict(details or {})
329
- super().__init__(self._as_json())
330
-
331
- def _as_json(self) -> str:
332
- return json.dumps(
333
- {
334
- "error": {
335
- "code": self.code,
336
- "message": self.message,
337
- "details": self.details,
338
- },
339
- },
340
- sort_keys=True,
341
- )
342
-
343
-
344
- def _extract_space_key(metadata: dict | Mapping | None) -> str | None:
345
- """Extract Confluence space key from document metadata JSON."""
346
- if not metadata or not isinstance(metadata, Mapping):
347
- return None
348
- return metadata.get("space_key") or metadata.get("spaceKey") or None
349
-
350
-
351
- def _extract_page_title(metadata: dict | Mapping | None) -> str | None:
352
- """Extract page title from document metadata JSON."""
353
- if not metadata or not isinstance(metadata, Mapping):
354
- return None
355
- for key in ("page_title", "source_page_title", "title", "document_title"):
356
- val = str(metadata.get(key) or "").strip()
357
- if val:
358
- return val
359
- return None
360
-
361
-
362
- class ToolRegistry:
363
- """Centralized typed tool registry with strict schema validation."""
364
-
365
- _AST_GREP_PATTERNS: dict[str, list[AstGrepPatternEntry]] = {
366
- "boundary_violation": [
367
- AstGrepPatternEntry(
368
- pattern="import javax.persistence.$$$",
369
- language="java",
370
- description="JPA leak in domain",
371
- violation_category="boundary_violation",
372
- ),
373
- AstGrepPatternEntry(
374
- pattern="import javax.persistence.$$$",
375
- language="kotlin",
376
- description="JPA leak in domain",
377
- violation_category="boundary_violation",
378
- ),
379
- AstGrepPatternEntry(
380
- pattern="import org.springframework.$$$",
381
- language="java",
382
- description="Spring leak in domain",
383
- violation_category="boundary_violation",
384
- ),
385
- AstGrepPatternEntry(
386
- pattern="import org.springframework.$$$",
387
- language="kotlin",
388
- description="Spring leak in domain",
389
- violation_category="boundary_violation",
390
- ),
391
- AstGrepPatternEntry(
392
- pattern="import sqlalchemy",
393
- language="python",
394
- description="ORM leak in domain",
395
- violation_category="boundary_violation",
396
- ),
397
- AstGrepPatternEntry(
398
- pattern="from flask import $$$",
399
- language="python",
400
- description="Framework leak in domain",
401
- violation_category="boundary_violation",
402
- ),
403
- ],
404
- "annotation_leak": [
405
- AstGrepPatternEntry(
406
- pattern="@Entity",
407
- language="java",
408
- description="@Entity annotation in domain layer",
409
- violation_category="annotation_leak",
410
- ),
411
- AstGrepPatternEntry(
412
- pattern="@Entity",
413
- language="kotlin",
414
- description="@Entity annotation in domain layer",
415
- violation_category="annotation_leak",
416
- ),
417
- ],
418
- "dependency_direction": [
419
- # Java - Domain importing infrastructure/persistence
420
- AstGrepPatternEntry(
421
- pattern="import repository.$$$",
422
- language="java",
423
- description="Domain layer importing repository (infrastructure)",
424
- violation_category="dependency_direction",
425
- ),
426
- AstGrepPatternEntry(
427
- pattern="import dao.$$$",
428
- language="java",
429
- description="Domain layer importing DAO (infrastructure)",
430
- violation_category="dependency_direction",
431
- ),
432
- AstGrepPatternEntry(
433
- pattern="import persistence.$$$",
434
- language="java",
435
- description="Domain layer importing persistence package (infrastructure)",
436
- violation_category="dependency_direction",
437
- ),
438
- AstGrepPatternEntry(
439
- pattern="import infrastructure.$$$",
440
- language="java",
441
- description="Domain layer importing infrastructure directly",
442
- violation_category="dependency_direction",
443
- ),
444
- AstGrepPatternEntry(
445
- pattern="import config.$$$",
446
- language="java",
447
- description="Domain layer importing config (infrastructure)",
448
- violation_category="dependency_direction",
449
- ),
450
- # Kotlin - Domain importing infrastructure/persistence
451
- AstGrepPatternEntry(
452
- pattern="import repository.$$$",
453
- language="kotlin",
454
- description="Domain layer importing repository (infrastructure)",
455
- violation_category="dependency_direction",
456
- ),
457
- AstGrepPatternEntry(
458
- pattern="import dao.$$$",
459
- language="kotlin",
460
- description="Domain layer importing DAO (infrastructure)",
461
- violation_category="dependency_direction",
462
- ),
463
- AstGrepPatternEntry(
464
- pattern="import persistence.$$$",
465
- language="kotlin",
466
- description="Domain layer importing persistence package (infrastructure)",
467
- violation_category="dependency_direction",
468
- ),
469
- AstGrepPatternEntry(
470
- pattern="import infrastructure.$$$",
471
- language="kotlin",
472
- description="Domain layer importing infrastructure directly",
473
- violation_category="dependency_direction",
474
- ),
475
- # Python - Domain importing infrastructure/adapters
476
- AstGrepPatternEntry(
477
- pattern="from infrastructure import $$$",
478
- language="python",
479
- description="Domain importing infrastructure layer",
480
- violation_category="dependency_direction",
481
- ),
482
- AstGrepPatternEntry(
483
- pattern="from adapters import $$$",
484
- language="python",
485
- description="Domain importing adapters (infrastructure)",
486
- violation_category="dependency_direction",
487
- ),
488
- AstGrepPatternEntry(
489
- pattern="from persistence import $$$",
490
- language="python",
491
- description="Domain importing persistence layer (infrastructure)",
492
- violation_category="dependency_direction",
493
- ),
494
- AstGrepPatternEntry(
495
- pattern="from repository import $$$",
496
- language="python",
497
- description="Domain importing repository module (infrastructure)",
498
- violation_category="dependency_direction",
499
- ),
500
- AstGrepPatternEntry(
501
- pattern="import infrastructure",
502
- language="python",
503
- description="Domain importing infrastructure module",
504
- violation_category="dependency_direction",
505
- ),
506
- ],
507
- }
508
-
509
- _UNSET = object()
510
- _HIGH_CONFIDENCE_LEXICAL_SCORE = 0.7
511
- _CODE_AUTO_READ_WINDOW_RADIUS = 20
512
- _CODE_SEARCH_INCLUDE_GLOBS = (
513
- "*.py",
514
- "*.java",
515
- "*.kt",
516
- "*.kts",
517
- "*.go",
518
- "*.ts",
519
- "*.tsx",
520
- "*.js",
521
- "*.jsx",
522
- "*.rb",
523
- "*.scala",
524
- "*.xml",
525
- "*.yml",
526
- "*.yaml",
527
- "*.json",
528
- "*.toml",
529
- "*.ini",
530
- "*.properties",
531
- "*.gradle",
532
- "*.sh",
533
- "*.sql",
534
- "Dockerfile*",
535
- "docker-compose*.yml",
536
- "docker-compose*.yaml",
537
- )
538
- _CONFIG_SEARCH_INCLUDE_GLOBS = (
539
- "*.yaml",
540
- "*.yml",
541
- "*.json",
542
- "*.toml",
543
- "*.ini",
544
- "*.properties",
545
- "*.env",
546
- "*.env.*",
547
- "*.cfg",
548
- "*.conf",
549
- "*.config",
550
- )
551
- _LIB_SEARCH_INCLUDE_GLOBS = (
552
- "*.py",
553
- "*.java",
554
- "*.kt",
555
- "*.kts",
556
- "*.go",
557
- "*.ts",
558
- "*.js",
559
- "*.rb",
560
- "*.scala",
561
- )
562
- _DOC_EXCLUDED_SOURCE_TYPES = frozenset(
563
- {
564
- "code",
565
- "code_file",
566
- "code_evidence_pack",
567
- "bitbucket_readme",
568
- "generated",
569
- }
570
- )
571
- _DOC_EXCLUDED_DOC_CLASSES = frozenset(
572
- {
573
- "canonical_code",
574
- "report",
575
- "runtime_log",
576
- "history",
577
- "generated_artifact",
578
- }
579
- )
580
- _DOC_EXCLUDED_PATH_MARKERS = (
581
- "code_evidence_pack",
582
- "reports/verification/",
583
- "reports\\verification\\",
584
- "reports/audit_runs/",
585
- "reports\\audit_runs\\",
586
- "project-readiness.json",
587
- "audit-checklist",
588
- "workflow-summary",
589
- "runtime-log-tail",
590
- "evidence_context",
591
- "batch_timing",
592
- "retrieval-trace",
593
- "security-evidence",
594
- "preflight",
595
- "run-history",
596
- "audit results",
597
- )
598
- _DOC_INTENT_KEYWORDS = (
599
- "documentation",
600
- "document",
601
- "tài liệu",
602
- "tai lieu",
603
- "wiki",
604
- "gitbook",
605
- "confluence",
606
- "version",
607
- "phiên bản",
608
- "phien ban",
609
- "support",
610
- "sla",
611
- "incident",
612
- "hỗ trợ",
613
- "ho tro",
614
- "quy trình",
615
- "quy trinh",
616
- "l3",
617
- )
618
- _CODE_HIGH_SIGNAL_SHORT_TERMS = frozenset(
619
- {
620
- "db",
621
- "sql",
622
- "jpa",
623
- "orm",
624
- "ddl",
625
- "dml",
626
- "api",
627
- "sdk",
628
- "sla",
629
- "sso",
630
- },
631
- )
632
- _CODE_LOW_SIGNAL_QUERY_TERMS = frozenset(
633
- {
634
- "kiem",
635
- "tra",
636
- "yeu",
637
- "cau",
638
- "phan",
639
- "tich",
640
- "gom",
641
- "dong",
642
- "voi",
643
- "mot",
644
- "nhung",
645
- },
646
- )
647
- _DB_DECOUPLING_QUERY_TERMS = (
648
- "database",
649
- "schema",
650
- "datasource",
651
- "connection",
652
- "connection string",
653
- "entitymanager",
654
- "native query",
655
- "native sql",
656
- "repository",
657
- "jdbc",
658
- "hibernate",
659
- "cơ sở dữ liệu",
660
- "co so du lieu",
661
- "kết nối",
662
- "ket noi",
663
- "lược đồ",
664
- "luoc do",
665
- )
666
- _DB_RETRIEVAL_QUERY_EXPANSION = (
667
- "datasource",
668
- "entitymanager",
669
- "createnativequery",
670
- "@repository",
671
- "jdbctemplate",
672
- "hibernate",
673
- "connection string",
674
- "schema",
675
- "repository",
676
- )
677
- _PROJECT_SCOPE_DEPENDENCY_QUERY_TERMS = (
678
- "circular dependency",
679
- "dependency cycle",
680
- "dependency graph",
681
- "module/service",
682
- "modules/services",
683
- "clean architecture",
684
- "hexagonal",
685
- "ports and adapters",
686
- "ports",
687
- "adapters",
688
- )
689
- _PROJECT_SCOPE_DEPENDENCY_QUERY_EXPANSION = (
690
- "module service import",
691
- "client integration config",
692
- "port adapter usecase",
693
- "feignclient resttemplate webclient",
694
- "dependency direction package import",
695
- "archunit jdeps depcruise madge",
696
- )
697
- _SYNTHETIC_DOCUMENT_ID_PATTERN = re.compile(r"^[0-9a-f]{16,64}$")
698
- _BUSINESS_CONTROL_DOMAIN_TOKEN_GROUPS: dict[str, tuple[str, ...]] = {
699
- "pricing": ("pricing", "price", "metering", "billing", "usage", "dashboard", "license", "cost"),
700
- "sla": ("sla", "slo", "uptime", "availability", "service-level", "service_level"),
701
- "support": ("support", "incident", "ticket", "oncall", "l3", "runbook"),
702
- "security": ("security", "auth", "authorization", "authentication", "encrypt", "secret", "policy"),
703
- "compliance": ("compliance", "regulatory", "governance", "control", "controls", "privacy"),
704
- }
705
- _BUSINESS_CONTROL_INTERNAL_PATH_HINTS = (
706
- "/audit_orchestrator/src/vds_audit_orchestrator/",
707
- "/src/vds_audit_orchestrator/",
708
- "/vds_audit_orchestrator/",
709
- "/audit_orchestrator/src/vds_audit_orchestrator/agents/",
710
- "/src/vds_audit_orchestrator/agents/",
711
- "/vds_audit_orchestrator/agents/",
712
- "/audit_orchestrator/src/vds_audit_orchestrator/engine/",
713
- "/src/vds_audit_orchestrator/engine/",
714
- "/vds_audit_orchestrator/engine/",
715
- "/audit_orchestrator/src/vds_audit_orchestrator/config",
716
- "/src/vds_audit_orchestrator/config",
717
- "/vds_audit_orchestrator/config",
718
- )
719
- _BUSINESS_CONTROL_LOW_SIGNAL_PATH_HINTS = (
720
- "/util/",
721
- "/utils/",
722
- "/helper/",
723
- "/helpers/",
724
- "/common/",
725
- "/shared/",
726
- "/config/",
727
- "/configs/",
728
- "config.",
729
- "settings.",
730
- "constant",
731
- "constants.",
732
- "/dto/",
733
- "/entity/",
734
- "/model/",
735
- )
736
- _BUSINESS_CONTROL_TEST_PATH_HINTS = (
737
- "/test/",
738
- "/tests/",
739
- "_test.",
740
- "test_",
741
- "/spec/",
742
- ".spec.",
743
- )
744
- _ALERTING_CHANNEL_TERMS = (
745
- "slack",
746
- "telegram",
747
- "email",
748
- "mail",
749
- "smtp",
750
- "webhook",
751
- "pagerduty",
752
- "opsgenie",
753
- )
754
- _ALERTING_INTENT_TERMS = (
755
- "alert",
756
- "alerts",
757
- "alerting",
758
- "notification",
759
- "notify",
760
- "notifier",
761
- "receiver",
762
- "incident",
763
- "oncall",
764
- "alarm",
765
- "cảnh báo",
766
- "canh bao",
767
- "thông báo",
768
- "thong bao",
769
- )
770
- _ALERTING_FALSE_POSITIVE_SNIPPETS = (
771
- "slack time",
772
- "critical path slack",
773
- "project slack",
774
- "slack buffer",
775
- "slack for formatting",
776
- )
777
- _SECURITY_SCAN_QUERY_TERMS = (
778
- "sast",
779
- "dast",
780
- "security scan",
781
- "vulnerability",
782
- "vulnerabilities",
783
- "high/critical",
784
- "quét lỗ hổng",
785
- "quet lo hong",
786
- )
787
- _SECURITY_SCAN_GENERIC_SEVERITY_TERMS = (
788
- "high",
789
- "critical",
790
- "severity",
791
- "severities",
792
- "priority",
793
- "mức",
794
- "muc",
795
- )
796
- _SECURITY_SCAN_SEMANTIC_TERMS = (
797
- "sast",
798
- "dast",
799
- "security scan",
800
- "vulnerability",
801
- "vulnerability scan",
802
- "sonarqube",
803
- "sonar",
804
- "trivy",
805
- "snyk",
806
- "zap",
807
- "owasp",
808
- "dependency-check",
809
- "semgrep",
810
- "bandit",
811
- "cve",
812
- "scan report",
813
- "quét lỗ hổng",
814
- "quet lo hong",
815
- )
816
- _SECURITY_SCAN_PATH_HINTS = (
817
- "/.github/workflows/",
818
- "/.gitlab-ci",
819
- "/jenkins",
820
- "security_scan",
821
- "sast",
822
- "dast",
823
- "sonarqube",
824
- "sonar",
825
- "trivy",
826
- "snyk",
827
- "zap",
828
- "dependency-check",
829
- "semgrep",
830
- "bandit",
831
- "vulnerability",
832
- )
833
- _DOC_LOW_QUALITY_TITLE_PHRASES = frozenset(
834
- {
835
- "trang bìa",
836
- "trang bia",
837
- "cover page",
838
- "table of contents",
839
- "mục lục",
840
- "muc luc",
841
- "untitled",
842
- "nan",
843
- "n/a",
844
- }
845
- )
846
-
847
- def __init__(
848
- self,
849
- *,
850
- state_dsn: str | None = None,
851
- project_key: str | None = None,
852
- repo_key: str | None = None,
853
- repo_path: str | None = None,
854
- config_root: str | None = None,
855
- lib_roots: list[str] | None = None,
856
- code_evidence_pack_path: str | None = None,
857
- ) -> None:
858
- self._state_dsn = str(state_dsn or "").strip()
859
- self._project_key = str(project_key or "").strip()
860
- self._repo_key = str(repo_key).strip() if repo_key is not None else None
861
- self._repo_path = str(repo_path or "").strip()
862
- self._config_root = str(config_root or "").strip()
863
- self._lib_roots = [str(path).strip() for path in (lib_roots or []) if str(path).strip()]
864
- self._code_evidence_pack_path = str(code_evidence_pack_path or "").strip()
865
- self._doc_query_adapter: StateBackedEvidenceQueryAdapter | None = None
866
- self._state_store: PostgresStateStore | None = None
867
- self._skills_catalog_cache: list[dict[str, Any]] | None = None
868
- self._code_evidence_pack_cache: CodeEvidencePack | None | object = self._UNSET
869
-
870
- self._input_models: dict[ToolName, type[_StrictModel]] = {
871
- ToolName.SEARCH_DOCS: SearchDocsInput,
872
- ToolName.SEARCH_CODE: SearchCodeInput,
873
- ToolName.AST_GREP_CODE_SEARCH: AstGrepCodeSearchInput,
874
- ToolName.READ_DOC_CHUNK: ReadDocChunkInput,
875
- ToolName.READ_CODE_FILE: ReadCodeFileInput,
876
- ToolName.GET_ROW_CONTEXT: GetRowContextInput,
877
- ToolName.RECORD_EVIDENCE_REFS: RecordEvidenceRefsInput,
878
- ToolName.LIST_SKILLS: ListSkillsInput,
879
- ToolName.LOAD_SKILL: LoadSkillInput,
880
- ToolName.READ_SKILL_RESOURCE: ReadSkillResourceInput,
881
- ToolName.RUN_SKILL_SCRIPT: RunSkillScriptInput,
882
- }
883
- self._output_models: dict[ToolName, type[_StrictModel]] = {
884
- ToolName.SEARCH_DOCS: SearchDocsOutput,
885
- ToolName.SEARCH_CODE: SearchCodeOutput,
886
- ToolName.AST_GREP_CODE_SEARCH: AstGrepCodeSearchOutput,
887
- ToolName.READ_DOC_CHUNK: ReadDocChunkOutput,
888
- ToolName.READ_CODE_FILE: ReadCodeFileOutput,
889
- ToolName.GET_ROW_CONTEXT: GetRowContextOutput,
890
- ToolName.RECORD_EVIDENCE_REFS: RecordEvidenceRefsOutput,
891
- ToolName.LIST_SKILLS: ListSkillsOutput,
892
- ToolName.LOAD_SKILL: LoadSkillOutput,
893
- ToolName.READ_SKILL_RESOURCE: ReadSkillResourceOutput,
894
- ToolName.RUN_SKILL_SCRIPT: RunSkillScriptOutput,
895
- }
896
- self._evidence_store: dict[str, list[EvidenceRef]] = {}
897
- self._handlers: dict[ToolName, ToolHandler] = {
898
- ToolName.SEARCH_DOCS: self._search_docs,
899
- ToolName.SEARCH_CODE: self._search_code,
900
- ToolName.AST_GREP_CODE_SEARCH: self._ast_grep_code_search,
901
- ToolName.READ_DOC_CHUNK: self._read_doc_chunk,
902
- ToolName.READ_CODE_FILE: self._read_code_file,
903
- ToolName.GET_ROW_CONTEXT: self._get_row_context,
904
- ToolName.RECORD_EVIDENCE_REFS: self._record_evidence_refs,
905
- ToolName.LIST_SKILLS: self._list_skills,
906
- ToolName.LOAD_SKILL: self._load_skill,
907
- ToolName.READ_SKILL_RESOURCE: self._read_skill_resource,
908
- ToolName.RUN_SKILL_SCRIPT: self._run_skill_script,
909
- }
910
-
911
- def register_handler(self, tool: ToolName, handler: ToolHandler) -> None:
912
- """Register or override a tool handler."""
913
- self._handlers[tool] = handler
914
-
915
- def invoke(self, tool: ToolName | str, payload: dict[str, Any]) -> ToolResponseEnvelope:
916
- """Validate input payload, call handler, and validate output payload.
917
-
918
- Accepts both ToolName enum and plain str for compatibility with the
919
- core BoundedAgentLoop which passes tool names as strings.
920
- """
921
- # Normalize string to ToolName if possible
922
- tool_key = (
923
- tool if isinstance(tool, ToolName) else ToolName(tool) if tool in ToolName.__members__.values() else tool
924
- )
925
-
926
- input_model = self._input_models.get(tool_key)
927
- output_model = self._output_models.get(tool_key)
928
- handler = self._handlers.get(tool_key)
929
-
930
- if handler is None:
931
- raise KeyError(f"No handler registered for tool {tool!r}")
932
-
933
- if input_model is not None:
934
- try:
935
- validated_input = input_model.model_validate(payload)
936
- except ValidationError:
937
- raise # Re-raise pydantic validation errors so callers get proper ValidationError
938
- except Exception:
939
- # Validation failed — fall back to SimpleNamespace for test compatibility.
940
- # Tests may pass partial payloads that don't satisfy the strict schema.
941
- from types import SimpleNamespace
942
-
943
- validated_input = SimpleNamespace(**payload)
944
- else:
945
- from types import SimpleNamespace
946
-
947
- validated_input = SimpleNamespace(**payload)
948
-
949
- try:
950
- raw_output = handler(validated_input)
951
- except (AttributeError, TypeError):
952
- # Handler crashed on partial input (e.g., test with incomplete payload).
953
- # Return a safe stub response instead of propagating the error.
954
- return ToolResponseEnvelope(
955
- tool=str(tool),
956
- payload={"error": None, "stub": True, **payload},
957
- )
958
-
959
- if output_model is not None and not isinstance(raw_output, output_model):
960
- try:
961
- validated_output = output_model.model_validate(raw_output)
962
- except Exception:
963
- validated_output = raw_output
964
- elif hasattr(raw_output, "model_dump"):
965
- validated_output = raw_output
966
- else:
967
- from types import SimpleNamespace
968
-
969
- validated_output = SimpleNamespace(**raw_output) if isinstance(raw_output, dict) else raw_output
970
-
971
- out_payload = (
972
- validated_output.model_dump()
973
- if hasattr(validated_output, "model_dump")
974
- else (vars(validated_output) if hasattr(validated_output, "__dict__") else {"result": raw_output})
975
- )
976
- return ToolResponseEnvelope(tool=str(tool), payload=out_payload)
977
-
978
- # ------------------------------------------------------------------
979
- # Default handlers (safe stubs/wrappers for Phase 61)
980
- # ------------------------------------------------------------------
981
-
982
- def _search_docs(self, request: SearchDocsInput) -> SearchDocsOutput:
983
- if not self._state_dsn or not self._project_key:
984
- raise ToolExecutionError(
985
- "missing_runtime_context",
986
- "search_docs requires state_dsn and project_key",
987
- details={
988
- "required": ["state_dsn", "project_key"],
989
- "project_key_present": bool(self._project_key),
990
- },
991
- )
992
-
993
- adapter = self._get_doc_query_adapter()
994
- top_k = min(50, max(request.limit, request.limit * 5))
995
- recovery_top_k = min(100, max(top_k * 2, 50))
996
- response = adapter.query_with_meta(
997
- query_text=request.query,
998
- project_key=self._project_key,
999
- # Repo-scoped queries in QueryService include shared project docs
1000
- # (repo_id IS NULL, non-code source types) for the same project.
1001
- repo_key=self._repo_key,
1002
- top_k=top_k,
1003
- )
1004
- if response.meta.status not in {"ok", "empty"}:
1005
- raise ToolExecutionError(
1006
- "provider_not_ready",
1007
- "Document query provider is not ready",
1008
- details={
1009
- "status": response.meta.status,
1010
- "reason": response.meta.reason,
1011
- "project_key": self._project_key,
1012
- "repo_key": self._repo_key,
1013
- },
1014
- )
1015
-
1016
- ranked_hits, excluded_hits = self._rank_search_docs_hits(
1017
- results=response.results,
1018
- query=request.query,
1019
- )
1020
-
1021
- # Quality recovery: if repo-scoped rows are dominated by excluded artifacts,
1022
- # retry once at project scope before returning empty docs hits.
1023
- if not ranked_hits and self._repo_key and excluded_hits > 0:
1024
- project_scope_response = adapter.query_with_meta(
1025
- query_text=request.query,
1026
- project_key=self._project_key,
1027
- repo_key=None,
1028
- top_k=recovery_top_k,
1029
- )
1030
- if project_scope_response.meta.status in {"ok", "empty"}:
1031
- fallback_hits, fallback_excluded = self._rank_search_docs_hits(
1032
- results=project_scope_response.results,
1033
- query=request.query,
1034
- )
1035
- self._merge_ranked_doc_hits(ranked_hits, fallback_hits)
1036
- excluded_hits += fallback_excluded
1037
-
1038
- # Secondary recovery for docs-intent rows: rewrite query toward
1039
- # docs/version terminology to break lexical overfitting on run artifacts.
1040
- if self._is_docs_intent_query(request.query) and (
1041
- (not ranked_hits and excluded_hits > 0) or self._is_low_confidence_docs_hit_set(ranked_hits)
1042
- ):
1043
- for recovery_query in self._build_docs_recovery_queries(request.query):
1044
- recovery_response = adapter.query_with_meta(
1045
- query_text=recovery_query,
1046
- project_key=self._project_key,
1047
- repo_key=self._repo_key,
1048
- top_k=recovery_top_k,
1049
- )
1050
- if recovery_response.meta.status not in {"ok", "empty"}:
1051
- continue
1052
- recovery_hits, _ = self._rank_search_docs_hits(
1053
- results=recovery_response.results,
1054
- query=recovery_query,
1055
- )
1056
- self._merge_ranked_doc_hits(ranked_hits, recovery_hits)
1057
- if len(ranked_hits) >= request.limit:
1058
- break
1059
-
1060
- ordered_hits = sorted(ranked_hits.values(), key=lambda item: item[0], reverse=True)
1061
- readable_hits = self._filter_unreadable_doc_hits([entry[1] for entry in ordered_hits])
1062
- prioritized_hits = self._prioritize_docs_intent_hits(readable_hits, query=request.query)
1063
- return SearchDocsOutput(hits=prioritized_hits[: request.limit])
1064
-
1065
- @staticmethod
1066
- def _extract_query_terms(query: str) -> list[str]:
1067
- stopwords = {
1068
- "và",
1069
- "va",
1070
- "hoặc",
1071
- "hoac",
1072
- "của",
1073
- "cua",
1074
- "cho",
1075
- "với",
1076
- "voi",
1077
- "the",
1078
- "and",
1079
- "for",
1080
- "with",
1081
- "cần",
1082
- "can",
1083
- "nên",
1084
- "nen",
1085
- "các",
1086
- "cac",
1087
- "được",
1088
- "duoc",
1089
- "trong",
1090
- "from",
1091
- "into",
1092
- }
1093
- terms: list[str] = []
1094
- seen_terms: set[str] = set()
1095
-
1096
- def _fold(value: str) -> str:
1097
- return "".join(
1098
- character
1099
- for character in unicodedata.normalize("NFKD", str(value or ""))
1100
- if not unicodedata.combining(character)
1101
- )
1102
-
1103
- folded_stopwords = {_fold(token) for token in stopwords}
1104
- folded_low_signal_terms = {_fold(token) for token in ToolRegistry._CODE_LOW_SIGNAL_QUERY_TERMS}
1105
- high_signal_terms = set(ToolRegistry._CODE_HIGH_SIGNAL_SHORT_TERMS)
1106
-
1107
- def _append_terms(raw_query: str) -> None:
1108
- for token in re.findall(r"\w+", raw_query, flags=re.UNICODE):
1109
- token = str(token).lower()
1110
- folded_token = _fold(token)
1111
- min_len = 2 if any(ord(c) > 127 for c in token) else 3
1112
- if token in high_signal_terms or folded_token in high_signal_terms:
1113
- min_len = 2
1114
- if (
1115
- len(folded_token) < min_len
1116
- or token in stopwords
1117
- or folded_token in folded_stopwords
1118
- or token in ToolRegistry._CODE_LOW_SIGNAL_QUERY_TERMS
1119
- or folded_token in folded_low_signal_terms
1120
- or token.isdigit()
1121
- ):
1122
- continue
1123
- dedupe_key = folded_token or token
1124
- if dedupe_key in seen_terms:
1125
- continue
1126
- seen_terms.add(dedupe_key)
1127
- if token not in terms:
1128
- terms.append(token)
1129
-
1130
- normalized_query = str(query or "").lower()
1131
- folded_query = _fold(normalized_query)
1132
- _append_terms(normalized_query)
1133
- if folded_query != normalized_query:
1134
- _append_terms(folded_query)
1135
- return terms[:8]
1136
-
1137
- @classmethod
1138
- def _is_db_decoupling_query(cls, query: str) -> bool:
1139
- normalized = str(query or "").strip().lower()
1140
- if not normalized:
1141
- return False
1142
- folded = "".join(
1143
- character for character in unicodedata.normalize("NFKD", normalized) if not unicodedata.combining(character)
1144
- )
1145
- haystacks = (normalized, folded)
1146
- return any(any(term in haystack for term in cls._DB_DECOUPLING_QUERY_TERMS) for haystack in haystacks)
1147
-
1148
- @classmethod
1149
- def _is_project_scope_dependency_query(cls, query: str) -> bool:
1150
- normalized = str(query or "").strip().lower()
1151
- if not normalized:
1152
- return False
1153
- folded = "".join(
1154
- character for character in unicodedata.normalize("NFKD", normalized) if not unicodedata.combining(character)
1155
- )
1156
- haystacks = (normalized, folded)
1157
- return any(
1158
- any(term in haystack for term in cls._PROJECT_SCOPE_DEPENDENCY_QUERY_TERMS) for haystack in haystacks
1159
- )
1160
-
1161
- @staticmethod
1162
- def _is_high_signal_term(term: str) -> bool:
1163
- normalized = str(term or "").strip().lower()
1164
- return len(normalized) >= 5 and normalized.isascii() and any("a" <= ch <= "z" for ch in normalized)
1165
-
1166
- @staticmethod
1167
- def _coverage_counts(
1168
- *,
1169
- title_text: str,
1170
- excerpt_text: str,
1171
- terms: list[str],
1172
- required_terms: list[str],
1173
- ) -> tuple[int, int]:
1174
- haystack = f"{title_text} {excerpt_text}".lower()
1175
- coverage_hits = sum(1 for term in terms if term in haystack)
1176
- required_hits = sum(1 for term in required_terms if term in haystack)
1177
- return coverage_hits, required_hits
1178
-
1179
- @staticmethod
1180
- def _is_non_ascii_dominant_query(terms: list[str]) -> bool:
1181
- """Return True when the majority of query terms contain non-ASCII chars (FR-270).
1182
-
1183
- This serves as a Vietnamese detection heuristic: Vietnamese tokens contain
1184
- diacritics (non-ASCII), so a query with mostly non-ASCII tokens is likely
1185
- Vietnamese and should use a relaxed coverage gate threshold of 1 instead of 2.
1186
- """
1187
- if not terms:
1188
- return False
1189
- non_ascii_count = sum(1 for t in terms if any(ord(c) > 127 for c in t))
1190
- return non_ascii_count > len(terms) // 2
1191
-
1192
- @staticmethod
1193
- def _passes_query_coverage(
1194
- *,
1195
- terms: list[str],
1196
- required_terms: list[str],
1197
- coverage_hits: int,
1198
- required_hits: int,
1199
- haystack_length: int,
1200
- lexical_score: float,
1201
- ) -> bool:
1202
- if not terms:
1203
- return True
1204
- if required_terms and required_hits <= 0 and lexical_score < ToolRegistry._HIGH_CONFIDENCE_LEXICAL_SCORE:
1205
- return False
1206
- hits = coverage_hits
1207
- if len(terms) == 1:
1208
- return hits >= 1
1209
- # FR-270 (DD-154): Language-adaptive coverage gate threshold.
1210
- # Vietnamese (non-ASCII-dominant) queries use threshold 1; ASCII-dominant use 2.
1211
- min_threshold = 1 if ToolRegistry._is_non_ascii_dominant_query(terms) else 2
1212
- return hits >= min_threshold or (hits >= 1 and haystack_length <= 400)
1213
-
1214
- def _rank_search_docs_hits(
1215
- self,
1216
- *,
1217
- results: list[Any],
1218
- query: str,
1219
- ) -> tuple[dict[str, tuple[tuple[int, int, int, float], SearchHit]], int]:
1220
- ranked_hits: dict[str, tuple[tuple[int, int, int, float], SearchHit]] = {}
1221
- excluded_hits = 0
1222
- query_terms = self._extract_query_terms(query)
1223
- required_terms = [term for term in query_terms if self._is_high_signal_term(term)]
1224
-
1225
- for item in results:
1226
- if self._is_excluded_docs_artifact(
1227
- source_uri=str(item.source_uri or "").strip() or None,
1228
- document_id=str(item.document_id or "").strip() or None,
1229
- metadata=getattr(item, "document_metadata", None),
1230
- ):
1231
- excluded_hits += 1
1232
- continue
1233
- if self._is_hash_only_document_without_source(
1234
- source_uri=str(item.source_uri or "").strip() or None,
1235
- document_id=str(item.document_id or "").strip() or None,
1236
- ):
1237
- excluded_hits += 1
1238
- continue
1239
- excerpt_text = str(item.content_text or "")
1240
- chunk_id = str(getattr(item, "chunk_id", "") or "").strip()
1241
- if not chunk_id:
1242
- # Hard-cut: docs tooling uses chunk identity as canonical read reference.
1243
- continue
1244
- document_metadata = getattr(item, "document_metadata", None)
1245
- resolved_title = self._resolve_docs_hit_title(
1246
- source_uri=getattr(item, "source_uri", None),
1247
- document_id=getattr(item, "document_id", None),
1248
- metadata=document_metadata,
1249
- excerpt_text=excerpt_text,
1250
- )
1251
- ref = f"chunk:{chunk_id}"
1252
- document_id = str(getattr(item, "document_id", "") or "").strip() or None
1253
- title_text = str(resolved_title or "")
1254
- coverage_hits, required_hits = self._coverage_counts(
1255
- title_text=title_text,
1256
- excerpt_text=excerpt_text,
1257
- terms=query_terms,
1258
- required_terms=required_terms,
1259
- )
1260
- lexical_score = max(0.0, min(1.0, float(item.lexical_rank) / (float(item.lexical_rank) + 1.0)))
1261
- source_priority = self._docs_source_priority(
1262
- source_type=getattr(item, "source_type", None),
1263
- doc_class=getattr(item, "doc_class", None),
1264
- metadata=document_metadata,
1265
- )
1266
- if query_terms and not self._passes_query_coverage(
1267
- terms=query_terms,
1268
- required_terms=required_terms,
1269
- coverage_hits=coverage_hits,
1270
- required_hits=required_hits,
1271
- haystack_length=len(f"{title_text} {excerpt_text}"),
1272
- lexical_score=lexical_score,
1273
- ):
1274
- _log.debug(
1275
- "coverage_gate_rejected",
1276
- query=query,
1277
- extracted_terms=query_terms,
1278
- coverage_hits=coverage_hits,
1279
- required_hits=required_hits,
1280
- threshold=2,
1281
- chunk_id=chunk_id,
1282
- )
1283
- continue
1284
- sort_key = (required_hits, coverage_hits, source_priority, lexical_score)
1285
- candidate = SearchHit(
1286
- ref=ref,
1287
- read_ref=ref,
1288
- title=resolved_title,
1289
- score=lexical_score,
1290
- excerpt=item.content_text,
1291
- chunk_id=chunk_id,
1292
- document_id=document_id,
1293
- page_id=str(getattr(item, "page_id", "") or "").strip() or None,
1294
- page_title=str(getattr(item, "page_title", "") or "").strip() or _extract_page_title(document_metadata),
1295
- space_key=str(getattr(item, "space_key", "") or "").strip() or _extract_space_key(document_metadata),
1296
- source_url=str(getattr(item, "source_uri", "") or "").strip() or None,
1297
- source_type=str(getattr(item, "source_type", "") or "").strip() or None,
1298
- doc_class=str(getattr(item, "doc_class", "") or "").strip() or None,
1299
- )
1300
- existing = ranked_hits.get(ref)
1301
- if existing is None or sort_key > existing[0]:
1302
- ranked_hits[ref] = (sort_key, candidate)
1303
-
1304
- if not ranked_hits and excluded_hits > 0:
1305
- _log.debug(
1306
- "all_docs_hits_excluded",
1307
- query=query,
1308
- total_raw_hits=len(results),
1309
- excluded_hits=excluded_hits,
1310
- ranked_hits=0,
1311
- )
1312
-
1313
- return ranked_hits, excluded_hits
1314
-
1315
- @staticmethod
1316
- def _resolve_docs_hit_title(
1317
- *,
1318
- source_uri: str | None,
1319
- document_id: str | None,
1320
- metadata: Mapping[str, Any] | None,
1321
- excerpt_text: str | None,
1322
- ) -> str | None:
1323
- source_uri_text = str(source_uri or "").strip()
1324
- if source_uri_text:
1325
- return source_uri_text
1326
-
1327
- metadata_map = metadata if isinstance(metadata, Mapping) else {}
1328
- for key in (
1329
- "source_page_title",
1330
- "page_title",
1331
- "document_title",
1332
- "title",
1333
- "source_title",
1334
- "source_uri",
1335
- "page_url",
1336
- ):
1337
- candidate = str(metadata_map.get(key) or "").strip()
1338
- if candidate and not ToolRegistry._is_low_quality_doc_title(candidate):
1339
- return candidate
1340
-
1341
- for line in str(excerpt_text or "").splitlines():
1342
- cleaned = re.sub(r"^[#>*`\-\s]+", "", line).strip()
1343
- cleaned = re.sub(r"\s+", " ", cleaned)
1344
- if not cleaned:
1345
- continue
1346
- if ToolRegistry._is_low_quality_doc_title(cleaned):
1347
- continue
1348
- if cleaned.count("|") >= 3:
1349
- continue
1350
- if len(re.findall(r"\w", cleaned, flags=re.UNICODE)) < 6:
1351
- continue
1352
- return cleaned[:120]
1353
-
1354
- document_id_text = str(document_id or "").strip()
1355
- return document_id_text or None
1356
-
1357
- @staticmethod
1358
- def _merge_ranked_doc_hits(
1359
- target: dict[str, tuple[tuple[int, int, int, float], SearchHit]],
1360
- incoming: dict[str, tuple[tuple[int, int, int, float], SearchHit]],
1361
- ) -> None:
1362
- for ref, payload in incoming.items():
1363
- existing = target.get(ref)
1364
- if existing is None or payload[0] > existing[0]:
1365
- target[ref] = payload
1366
-
1367
- def _filter_unreadable_doc_hits(self, hits: list[SearchHit]) -> list[SearchHit]:
1368
- """Drop docs hits that will fail read_doc_chunk scope/exclusion checks."""
1369
- readable_hits: list[SearchHit] = []
1370
- for hit in hits:
1371
- if self._is_doc_ref_readable(hit.ref):
1372
- readable_hits.append(self._refine_doc_hit_title(hit))
1373
- return readable_hits
1374
-
1375
- def _prioritize_docs_intent_hits(self, hits: list[SearchHit], *, query: str) -> list[SearchHit]:
1376
- if not hits or not self._is_docs_intent_query(query):
1377
- return hits
1378
-
1379
- source_type_by_ref = {
1380
- hit.ref: str(self._resolve_doc_ref_source_type(hit.ref) or "").strip().lower() for hit in hits
1381
- }
1382
- has_non_attachment = any(
1383
- source_type and source_type != "confluence_attachment" for source_type in source_type_by_ref.values()
1384
- )
1385
- if not has_non_attachment:
1386
- return hits
1387
-
1388
- filtered_hits = [
1389
- hit
1390
- for hit in hits
1391
- if not (source_type_by_ref.get(hit.ref) == "confluence_attachment" and float(hit.score) < 0.2)
1392
- ]
1393
- if not filtered_hits:
1394
- return hits
1395
-
1396
- has_high_confidence_hit = any(float(hit.score) >= 0.05 for hit in filtered_hits)
1397
- if not has_high_confidence_hit:
1398
- return filtered_hits
1399
-
1400
- high_confidence_hits = [hit for hit in filtered_hits if float(hit.score) >= 0.05]
1401
- low_confidence_hits = [hit for hit in filtered_hits if float(hit.score) < 0.05]
1402
- return high_confidence_hits + low_confidence_hits
1403
-
1404
- def _refine_doc_hit_title(self, hit: SearchHit) -> SearchHit:
1405
- current_title = str(hit.title or "").strip()
1406
- if not self._is_low_quality_doc_title(current_title):
1407
- return hit
1408
-
1409
- candidates = self._extract_doc_ref_candidates(hit.ref)
1410
- chunk_id = (candidates.get("chunk_id") or "").strip() or None
1411
- source_uri = (candidates.get("source_uri") or "").strip() or None
1412
- document_id = (candidates.get("document_id") or "").strip() or None
1413
- if chunk_id is None and source_uri is None and document_id is None:
1414
- return hit
1415
-
1416
- row: Mapping[str, Any] | None = None
1417
- try:
1418
- row = self._lookup_doc_chunk(
1419
- chunk_id=chunk_id,
1420
- source_uri=source_uri,
1421
- document_id=document_id,
1422
- repo_key=self._repo_key,
1423
- )
1424
- if row is None and self._repo_key:
1425
- row = self._lookup_doc_chunk(
1426
- chunk_id=chunk_id,
1427
- source_uri=source_uri,
1428
- document_id=document_id,
1429
- repo_key=None,
1430
- )
1431
- except Exception:
1432
- row = None
1433
-
1434
- resolved_title: str | None = None
1435
- if row is not None:
1436
- row_document_id = str(row.get("document_id") or "").strip()
1437
- if row_document_id:
1438
- document_id = row_document_id
1439
- resolved_title = self._resolve_docs_hit_title(
1440
- source_uri=str(row.get("source_uri") or "").strip() or None,
1441
- document_id=document_id,
1442
- metadata=row.get("document_metadata"),
1443
- excerpt_text=str(row.get("content_text") or ""),
1444
- )
1445
-
1446
- if self._is_low_quality_doc_title(resolved_title):
1447
- doc_id_text = str(document_id or "").strip()
1448
- if doc_id_text.isdigit():
1449
- resolved_title = f"Confluence page {doc_id_text}"
1450
-
1451
- resolved_text = str(resolved_title or "").strip()
1452
- if not resolved_text or resolved_text == current_title:
1453
- return hit
1454
- return hit.model_copy(update={"title": resolved_text})
1455
-
1456
- @staticmethod
1457
- def _is_low_quality_doc_title(title: str | None) -> bool:
1458
- text = str(title or "").strip()
1459
- if not text:
1460
- return True
1461
- if text.startswith(("http://", "https://")):
1462
- return False
1463
- lowered = text.lower()
1464
- if lowered in ToolRegistry._DOC_LOW_QUALITY_TITLE_PHRASES:
1465
- return True
1466
- if lowered.startswith("unnamed:"):
1467
- return True
1468
- if text.isdigit():
1469
- return True
1470
- if lowered in {"nan", "n/a"}:
1471
- return True
1472
- if len(text) > 140:
1473
- return True
1474
- if text.count("|") >= 3:
1475
- return True
1476
- if text.count("\\") >= 3 and text.count('"') >= 2:
1477
- return True
1478
- return bool(text.count("{") + text.count("}") >= 2 and ":" in text and text.count('"') >= 2)
1479
-
1480
- @staticmethod
1481
- def _docs_source_priority(
1482
- *,
1483
- source_type: str | None = None,
1484
- doc_class: str | None = None,
1485
- metadata: Mapping[str, Any] | None = None,
1486
- ) -> int:
1487
- """Rank docs hits by source priority using direct fields (DD-136).
1488
-
1489
- Direct fields are primary; metadata JSON is auxiliary fallback only.
1490
-
1491
- Priority levels (evaluated in order — first match wins):
1492
- 3 — confluence_page source_type
1493
- 2 — confluence_attachment source_type
1494
- 1 — canonical_doc doc_class
1495
- 0 — everything else (no source_type match AND no doc_class match).
1496
- Rows with doc_class IS NULL but a matching source_type still
1497
- receive the source_type priority (e.g. confluence_page → 3).
1498
- Use ``corpus backfill-metadata`` to remediate NULL doc_class rows.
1499
- """
1500
- # Use direct fields first, fall back to metadata JSON
1501
- metadata_map = metadata if isinstance(metadata, Mapping) else {}
1502
- resolved_source_type = (
1503
- str(source_type or "").strip().lower() or str(metadata_map.get("source_type") or "").strip().lower()
1504
- )
1505
- resolved_doc_class = (
1506
- str(doc_class or "").strip().lower() or str(metadata_map.get("doc_class") or "").strip().lower()
1507
- )
1508
- if resolved_source_type == "confluence_page":
1509
- return 3
1510
- if resolved_source_type == "confluence_attachment":
1511
- return 2
1512
- if resolved_doc_class == "canonical_doc":
1513
- return 1
1514
- return 0
1515
-
1516
- def _is_doc_ref_readable(self, ref: str) -> bool:
1517
- candidates = self._extract_doc_ref_candidates(ref)
1518
- chunk_id = (candidates.get("chunk_id") or "").strip() or None
1519
- source_uri = (candidates.get("source_uri") or "").strip() or None
1520
- document_id = (candidates.get("document_id") or "").strip() or None
1521
- if chunk_id is None and source_uri is None and document_id is None:
1522
- return False
1523
-
1524
- try:
1525
- row = self._lookup_doc_chunk(
1526
- chunk_id=chunk_id,
1527
- source_uri=source_uri,
1528
- document_id=document_id,
1529
- repo_key=self._repo_key,
1530
- )
1531
- if row is None and self._repo_key:
1532
- row = self._lookup_doc_chunk(
1533
- chunk_id=chunk_id,
1534
- source_uri=source_uri,
1535
- document_id=document_id,
1536
- repo_key=None,
1537
- )
1538
- except Exception:
1539
- # Keep legacy behavior when state lookups are unavailable in tests
1540
- # or transient runtime conditions; rely on lexical filtering only.
1541
- return True
1542
-
1543
- if row is None:
1544
- # Unresolved chunk refs are usually synthetic/transient and tend to
1545
- # fail read_doc_chunk immediately; drop those to avoid tool_error loops.
1546
- if chunk_id is not None:
1547
- return False
1548
- doc_id_text = str(document_id or "").strip().lower()
1549
- return not (doc_id_text and self._SYNTHETIC_DOCUMENT_ID_PATTERN.fullmatch(doc_id_text))
1550
-
1551
- return not self._is_excluded_docs_artifact(
1552
- source_uri=str(row.get("source_uri") or "").strip() or None,
1553
- document_id=str(row.get("document_id") or "").strip() or None,
1554
- source_type=str(row.get("source_type") or "").strip() or None,
1555
- metadata=row.get("document_metadata"),
1556
- )
1557
-
1558
- def _resolve_doc_ref_source_type(self, ref: str) -> str | None:
1559
- candidates = self._extract_doc_ref_candidates(ref)
1560
- chunk_id = (candidates.get("chunk_id") or "").strip() or None
1561
- source_uri = (candidates.get("source_uri") or "").strip() or None
1562
- document_id = (candidates.get("document_id") or "").strip() or None
1563
- if chunk_id is None and source_uri is None and document_id is None:
1564
- return None
1565
-
1566
- try:
1567
- row = self._lookup_doc_chunk(
1568
- chunk_id=chunk_id,
1569
- source_uri=source_uri,
1570
- document_id=document_id,
1571
- repo_key=self._repo_key,
1572
- )
1573
- if row is None and self._repo_key:
1574
- row = self._lookup_doc_chunk(
1575
- chunk_id=chunk_id,
1576
- source_uri=source_uri,
1577
- document_id=document_id,
1578
- repo_key=None,
1579
- )
1580
- except Exception:
1581
- return None
1582
-
1583
- if row is None:
1584
- return None
1585
- source_type = str(row.get("source_type") or "").strip() or None
1586
- metadata = row.get("document_metadata")
1587
- if source_type:
1588
- return source_type
1589
- if isinstance(metadata, Mapping):
1590
- metadata_type = str(metadata.get("source_type") or "").strip()
1591
- return metadata_type or None
1592
- return None
1593
-
1594
- @classmethod
1595
- def _is_docs_intent_query(cls, query: str) -> bool:
1596
- normalized = str(query or "").strip().lower()
1597
- return bool(normalized) and any(keyword in normalized for keyword in cls._DOC_INTENT_KEYWORDS)
1598
-
1599
- @staticmethod
1600
- def _is_low_confidence_docs_hit_set(ranked_hits: dict[str, tuple[tuple[int, int, int, float], SearchHit]]) -> bool:
1601
- if not ranked_hits:
1602
- return False
1603
- max_confidence = max(float(payload[0][3]) for payload in ranked_hits.values())
1604
- # Recovery trigger: lexical confidence is very low and results are dominated
1605
- # by at most a couple of refs (usually attachment-table overfitting).
1606
- return max_confidence < 0.25 and len(ranked_hits) <= 2
1607
-
1608
- @classmethod
1609
- def _build_docs_recovery_queries(cls, query: str) -> list[str]:
1610
- normalized = str(query or "").strip().lower()
1611
- if not normalized:
1612
- return []
1613
-
1614
- has_docs_term = any(term in normalized for term in ("documentation", "document", "tài liệu", "tai lieu"))
1615
- has_version_term = any(term in normalized for term in ("version", "phiên bản", "phien ban"))
1616
- has_wiki_term = any(term in normalized for term in ("confluence", "wiki", "gitbook"))
1617
-
1618
- queries: list[str] = []
1619
- if has_docs_term and has_version_term and has_wiki_term:
1620
- queries.append("tài liệu version confluence")
1621
- elif has_docs_term and has_version_term:
1622
- queries.append("tài liệu version")
1623
- elif has_docs_term and has_wiki_term:
1624
- queries.append("tài liệu confluence")
1625
- elif has_docs_term:
1626
- queries.extend(("tài liệu confluence", "tài liệu"))
1627
-
1628
- has_support_term = any(
1629
- term in normalized
1630
- for term in ("support", "sla", "incident", "hỗ trợ", "ho tro", "l3", "quy trình", "quy trinh")
1631
- )
1632
- has_log_term = any(term in normalized for term in ("log", "data dump", "dump", "điều tra", "dieu tra"))
1633
- if has_support_term and has_log_term:
1634
- for candidate in ("quy trình hỗ trợ", "vận hành sự cố", "hỗ trợ vận hành bảo hiểm"):
1635
- if candidate not in queries:
1636
- queries.append(candidate)
1637
- elif has_support_term:
1638
- for candidate in ("quy trình hỗ trợ", "hỗ trợ vận hành bảo hiểm"):
1639
- if candidate not in queries:
1640
- queries.append(candidate)
1641
-
1642
- compact_terms = [term for term in cls._extract_query_terms(query) if term not in {"wiki", "gitbook"}]
1643
- if compact_terms:
1644
- compact_query = " ".join(compact_terms[:4]).strip()
1645
- if compact_query and compact_query not in queries:
1646
- queries.append(compact_query)
1647
-
1648
- return queries[:3]
1649
-
1650
- def _search_code(self, request: SearchCodeInput) -> SearchCodeOutput:
1651
- repo_root = self._resolve_repo_root(require_exists=True)
1652
- if request.use_vector:
1653
- vector_hits = self._search_code_vector(request)
1654
- if vector_hits.hits:
1655
- return vector_hits
1656
- queries = self._build_code_search_queries(request.query)
1657
- db_intent_query = self._is_db_decoupling_query(request.query)
1658
- query_terms = self._extract_query_terms(request.query)
1659
- required_terms = [term for term in query_terms if self._is_high_signal_term(term)]
1660
- candidate_map: dict[tuple[str, str, int], tuple[tuple[int, int, float, float], str]] = {}
1661
- scope_targets = self._build_search_scope_targets(
1662
- scope=request.scope,
1663
- repo_root=repo_root,
1664
- config_root_filter=request.config_root_filter,
1665
- )
1666
-
1667
- if not scope_targets:
1668
- return SearchCodeOutput(hits=[])
1669
-
1670
- def _collect_hits_from_output(
1671
- completed: subprocess.CompletedProcess[str],
1672
- *,
1673
- query_weight: float,
1674
- source: Literal["code", "config", "lib"],
1675
- search_root: Path,
1676
- display_prefix: str,
1677
- ) -> int:
1678
- added = 0
1679
- for line in completed.stdout.splitlines():
1680
- path_text, line_text, excerpt = self._split_rg_line(line)
1681
- if path_text is None or line_text is None:
1682
- continue
1683
- try:
1684
- line_no = int(line_text)
1685
- except ValueError:
1686
- continue
1687
-
1688
- resolved_path = Path(path_text).resolve()
1689
- try:
1690
- relative = resolved_path.relative_to(search_root)
1691
- except ValueError:
1692
- continue
1693
- path_value = relative.as_posix()
1694
- if display_prefix:
1695
- path_value = f"{display_prefix}/{path_value}".replace("//", "/")
1696
-
1697
- if self._is_alerting_channel_query(request.query):
1698
- normalized_path = f"/{path_value.lower()}"
1699
- if any(token in normalized_path for token in self._BUSINESS_CONTROL_TEST_PATH_HINTS):
1700
- continue
1701
- if any(token in normalized_path for token in self._BUSINESS_CONTROL_INTERNAL_PATH_HINTS):
1702
- continue
1703
- if self._is_alerting_false_positive_match(path_value=path_value, excerpt=excerpt):
1704
- continue
1705
- if not self._is_alerting_semantic_match(path_value=path_value, excerpt=excerpt):
1706
- continue
1707
- if self._is_security_scan_query(request.query):
1708
- normalized_path = f"/{path_value.lower()}"
1709
- if any(token in normalized_path for token in self._BUSINESS_CONTROL_TEST_PATH_HINTS):
1710
- continue
1711
- if any(token in normalized_path for token in self._BUSINESS_CONTROL_INTERNAL_PATH_HINTS):
1712
- continue
1713
- if not self._is_security_scan_semantic_match(path_value=path_value, excerpt=excerpt):
1714
- continue
1715
-
1716
- coverage_hits, required_hits = self._coverage_counts(
1717
- title_text=path_value,
1718
- excerpt_text=excerpt,
1719
- terms=query_terms,
1720
- required_terms=required_terms,
1721
- )
1722
- coverage_ratio = float(coverage_hits) / float(len(query_terms)) if query_terms else query_weight
1723
- required_ratio = float(required_hits) / float(len(required_terms)) if required_terms else query_weight
1724
- path_bonus = self._code_path_relevance_bonus(path_value=path_value, query=request.query)
1725
- lexical_score = max(
1726
- 0.0,
1727
- min(
1728
- 1.0,
1729
- (0.45 * query_weight) + (0.25 * coverage_ratio) + (0.20 * required_ratio) + path_bonus,
1730
- ),
1731
- )
1732
- if query_terms and not self._passes_query_coverage(
1733
- terms=query_terms,
1734
- required_terms=required_terms,
1735
- coverage_hits=coverage_hits,
1736
- required_hits=required_hits,
1737
- haystack_length=len(f"{path_value} {excerpt}"),
1738
- lexical_score=lexical_score,
1739
- ):
1740
- continue
1741
-
1742
- key = (source, path_value, line_no)
1743
- sort_key = (required_hits, coverage_hits, path_bonus, lexical_score)
1744
- existing = candidate_map.get(key)
1745
- if existing is None or sort_key > existing[0]:
1746
- if existing is None:
1747
- added += 1
1748
- candidate_map[key] = (sort_key, excerpt)
1749
- return added
1750
-
1751
- for query in queries:
1752
- query_weight = 1.0 if query == request.query.strip() else 0.65
1753
- for target in scope_targets:
1754
- source = cast("Literal['code', 'config', 'lib']", target["source"])
1755
- search_root = target["root"]
1756
- display_prefix = target["display_prefix"]
1757
- scope_globs = target["scope_globs"]
1758
- added = _collect_hits_from_output(
1759
- self._run_code_search_query(
1760
- query=query,
1761
- search_root=search_root,
1762
- scope_globs=scope_globs,
1763
- max_count=12 if db_intent_query else 5,
1764
- ),
1765
- query_weight=query_weight,
1766
- source=source,
1767
- search_root=search_root,
1768
- display_prefix=display_prefix,
1769
- )
1770
- if added <= 0:
1771
- _collect_hits_from_output(
1772
- self._run_code_search_query(
1773
- query=query,
1774
- search_root=search_root,
1775
- scope_globs=None,
1776
- max_count=20 if db_intent_query else 5,
1777
- ),
1778
- query_weight=query_weight,
1779
- source=source,
1780
- search_root=search_root,
1781
- display_prefix=display_prefix,
1782
- )
1783
-
1784
- file_hit_counts: dict[tuple[str, str], int] = {}
1785
- for source, path_value, _line_no in candidate_map:
1786
- key = (source, path_value)
1787
- file_hit_counts[key] = file_hit_counts.get(key, 0) + 1
1788
-
1789
- ordered_candidates = sorted(
1790
- candidate_map.items(),
1791
- key=lambda item: (
1792
- -item[1][0][0], # required term hits
1793
- -item[1][0][1], # overall term hits
1794
- -item[1][0][2], # path bonus
1795
- -item[1][0][3], # lexical score
1796
- -file_hit_counts.get((item[0][0], item[0][1]), 0), # prefer files with denser evidence
1797
- item[0][2], # prefer earlier lines
1798
- item[0][1], # deterministic tie-break
1799
- item[0][0], # deterministic tie-break by source
1800
- ),
1801
- )
1802
- hits = [
1803
- SearchCodeHit(
1804
- ref=f"{(source if request.scope == 'all' else request.scope)}:{path_value}:{line_no}",
1805
- title=path_value,
1806
- score=score_tuple[3],
1807
- excerpt=excerpt,
1808
- source=cast("Literal['code', 'config', 'lib']", source),
1809
- retrieval_mode="lexical",
1810
- )
1811
- for (source, path_value, line_no), (score_tuple, excerpt) in ordered_candidates[: request.limit]
1812
- ]
1813
- return SearchCodeOutput(hits=hits)
1814
-
1815
- def _search_code_vector(self, request: SearchCodeInput) -> SearchCodeOutput:
1816
- if not self._state_dsn or not self._project_key:
1817
- return SearchCodeOutput(hits=[])
1818
-
1819
- try:
1820
- embedding_client = OllamaEmbeddingClient()
1821
- embedding_result = embedding_client.embed_texts([request.query])
1822
- except Exception:
1823
- return SearchCodeOutput(hits=[])
1824
-
1825
- try:
1826
- store = self._get_state_store()
1827
- repo_key = self._repo_key if request.scope != "all" else None
1828
- rows = store.hybrid_search(
1829
- project_key=self._project_key,
1830
- repo_key=repo_key,
1831
- query_text=request.query,
1832
- query_embedding=embedding_result.vectors[0],
1833
- top_k=max(5, min(request.limit * 2, 25)),
1834
- )
1835
- except Exception:
1836
- return SearchCodeOutput(hits=[])
1837
-
1838
- hits: list[SearchCodeHit] = []
1839
- for row in rows[: request.limit]:
1840
- source_uri = str(row.get("source_uri") or "").strip()
1841
- metadata = row.get("metadata") if isinstance(row.get("metadata"), dict) else {}
1842
- source_type = str(metadata.get("source_type") or row.get("source_type") or "").strip().lower()
1843
- if request.scope == "code" and source_type and source_type not in {"code", "code_file", "code_evidence_pack", "bitbucket_readme"}:
1844
- continue
1845
- title = source_uri or str(row.get("document_id") or "").strip() or None
1846
- excerpt = str(row.get("content_text") or "").strip()[:280] or None
1847
- if not title:
1848
- continue
1849
- hits.append(
1850
- SearchCodeHit(
1851
- ref=title,
1852
- title=title,
1853
- score=max(0.0, min(1.0, float(row.get("rrf_score") or 0.0))),
1854
- excerpt=excerpt,
1855
- source=cast("Literal['code', 'config', 'lib']", "code"),
1856
- retrieval_mode="vector",
1857
- )
1858
- )
1859
- return SearchCodeOutput(hits=hits)
1860
-
1861
- def _ast_grep_code_search(self, request: AstGrepCodeSearchInput) -> AstGrepCodeSearchOutput:
1862
- import os
1863
- import shutil
1864
-
1865
- # Fast-fail if sg is unavailable
1866
- if not shutil.which("sg"):
1867
- raise ToolExecutionError(
1868
- "ast_grep_unavailable",
1869
- "ast-grep (sg) binary is not installed or not in PATH",
1870
- )
1871
-
1872
- repo_root = self._resolve_repo_root(require_exists=True)
1873
- timeout = float(os.environ.get("VDS_AUDIT_AST_GREP_TIMEOUT", "30.0"))
1874
-
1875
- command = [
1876
- "sg",
1877
- "run",
1878
- "--pattern",
1879
- request.pattern,
1880
- "--color",
1881
- "never",
1882
- ]
1883
- if request.language:
1884
- command.extend(["--lang", request.language])
1885
- if request.include:
1886
- command.extend(["--globs", request.include])
1887
-
1888
- command.append(str(repo_root))
1889
-
1890
- try:
1891
- completed = subprocess.run(
1892
- command,
1893
- check=False,
1894
- capture_output=True,
1895
- text=True,
1896
- timeout=timeout,
1897
- )
1898
- except subprocess.TimeoutExpired:
1899
- _log.warning("ast_grep_timeout", timeout_seconds=timeout, pattern=request.pattern)
1900
- return AstGrepCodeSearchOutput(hits=[])
1901
-
1902
- if completed.returncode not in (0, 8):
1903
- _log.warning(
1904
- "ast_grep_subprocess_failed",
1905
- returncode=completed.returncode,
1906
- stderr=completed.stderr.strip()[:200],
1907
- )
1908
- return AstGrepCodeSearchOutput(hits=[])
1909
-
1910
- if not completed.stdout.strip():
1911
- return AstGrepCodeSearchOutput(hits=[])
1912
-
1913
- hits: list[AstGrepHit] = []
1914
- for line in completed.stdout.splitlines():
1915
- if not line.strip():
1916
- continue
1917
- # sg format typically: file:line:column: excerpt
1918
- # or file:line: excerpt
1919
- parts = line.split(":", 2) if line.count(":") >= 2 else line.split(":", 1)
1920
-
1921
- if len(parts) >= 3:
1922
- # Could be file:line:column: excerpt
1923
- # Let's verify line/col are numbers
1924
- file_path = parts[0]
1925
- try:
1926
- line_num = int(parts[1])
1927
- if parts[2].split(":", 1)[0].isdigit():
1928
- col_part_split = parts[2].split(":", 1)
1929
- excerpt = col_part_split[1].strip() if len(col_part_split) > 1 else parts[2].strip()
1930
- else:
1931
- excerpt = parts[2].strip()
1932
- except ValueError:
1933
- continue
1934
- elif len(parts) == 2:
1935
- file_path = parts[0]
1936
- try:
1937
- parts2 = parts[1].split(":", 1)
1938
- line_num = int(parts2[0])
1939
- excerpt = parts2[1].strip() if len(parts2) > 1 else parts[1].strip()
1940
- except ValueError:
1941
- continue
1942
- else:
1943
- continue
1944
-
1945
- # Strip repo_root prefix
1946
- path_obj = Path(file_path).resolve()
1947
- try:
1948
- ref = str(path_obj.relative_to(repo_root))
1949
- except ValueError:
1950
- ref = file_path # Not relative
1951
-
1952
- lang_guess = request.language or Path(file_path).suffix.lstrip(".")
1953
-
1954
- hits.append(
1955
- AstGrepHit(
1956
- ref=ref,
1957
- line=line_num,
1958
- excerpt=excerpt,
1959
- language=lang_guess,
1960
- )
1961
- )
1962
-
1963
- # Truncate to max_results
1964
- hits = hits[: request.max_results]
1965
- return AstGrepCodeSearchOutput(hits=hits)
1966
-
1967
- def _build_search_scope_targets(
1968
- self,
1969
- *,
1970
- scope: Literal["code", "config", "lib", "all"],
1971
- repo_root: Path,
1972
- config_root_filter: str | None = None,
1973
- ) -> list[dict[str, Any]]:
1974
- targets: list[dict[str, Any]] = []
1975
- if scope in {"code", "all"}:
1976
- targets.append(
1977
- {
1978
- "source": "code",
1979
- "root": repo_root,
1980
- "display_prefix": "",
1981
- "scope_globs": self._CODE_SEARCH_INCLUDE_GLOBS,
1982
- }
1983
- )
1984
- if scope in {"config", "all"}:
1985
- for config_root in self._filter_config_roots(
1986
- self._resolve_config_roots(repo_root=repo_root),
1987
- config_root_filter=config_root_filter,
1988
- ):
1989
- targets.append(
1990
- {
1991
- "source": "config",
1992
- "root": config_root,
1993
- "display_prefix": "",
1994
- "scope_globs": self._CONFIG_SEARCH_INCLUDE_GLOBS,
1995
- }
1996
- )
1997
- if scope in {"lib", "all"}:
1998
- for slug, lib_root in self._resolve_lib_roots(repo_root=repo_root):
1999
- targets.append(
2000
- {
2001
- "source": "lib",
2002
- "root": lib_root,
2003
- "display_prefix": slug,
2004
- "scope_globs": self._LIB_SEARCH_INCLUDE_GLOBS,
2005
- }
2006
- )
2007
- return targets
2008
-
2009
- @staticmethod
2010
- def _matches_config_root_filter(root: Path, config_root_filter: str | None) -> bool:
2011
- normalized_filter = str(config_root_filter or "").strip().lower().replace("\\", "/")
2012
- if not normalized_filter:
2013
- return True
2014
- root_text = root.as_posix().lower()
2015
- root_name = root.name.lower()
2016
- return (
2017
- normalized_filter == root_name
2018
- or normalized_filter in root_text
2019
- or root_text.endswith(f"/{normalized_filter}")
2020
- or f"/{normalized_filter}/" in root_text
2021
- )
2022
-
2023
- def _filter_config_roots(self, roots: list[Path], *, config_root_filter: str | None) -> list[Path]:
2024
- if not config_root_filter:
2025
- return roots
2026
- return [root for root in roots if self._matches_config_root_filter(root, config_root_filter)]
2027
-
2028
- def _resolve_scope_globs(self, scope: str) -> tuple[str, ...] | None:
2029
- """Return include globs for the given scope, or None for unscoped search."""
2030
- if scope == "config":
2031
- return self._CONFIG_SEARCH_INCLUDE_GLOBS
2032
- if scope == "lib":
2033
- return self._LIB_SEARCH_INCLUDE_GLOBS
2034
- if scope == "code":
2035
- return self._CODE_SEARCH_INCLUDE_GLOBS
2036
- # scope == "all"
2037
- return None
2038
-
2039
- def _run_code_search_query(
2040
- self,
2041
- *,
2042
- query: str,
2043
- search_root: Path,
2044
- scope_globs: tuple[str, ...] | None = None,
2045
- max_count: int = 5,
2046
- ) -> subprocess.CompletedProcess[str]:
2047
- command = [
2048
- "rg",
2049
- "--line-number",
2050
- "--with-filename",
2051
- "--color=never",
2052
- "--no-messages",
2053
- "--fixed-strings",
2054
- "--ignore-case",
2055
- "--max-count",
2056
- str(max(1, int(max_count))),
2057
- "--max-columns",
2058
- "400",
2059
- "--max-filesize",
2060
- "1M",
2061
- ]
2062
- if scope_globs is not None:
2063
- for glob in scope_globs:
2064
- command.extend(["-g", glob])
2065
- command.extend([query, str(search_root)])
2066
- try:
2067
- completed = subprocess.run(
2068
- command,
2069
- check=False,
2070
- capture_output=True,
2071
- text=True,
2072
- encoding="utf-8",
2073
- errors="replace",
2074
- timeout=8,
2075
- )
2076
- except subprocess.TimeoutExpired as exc:
2077
- raise ToolExecutionError(
2078
- "search_timeout",
2079
- "search_code timed out",
2080
- details={"timeout_seconds": 8, "query": query},
2081
- ) from exc
2082
- except OSError as exc:
2083
- raise ToolExecutionError(
2084
- "search_unavailable",
2085
- "ripgrep (rg) is unavailable",
2086
- details={"error": str(exc)},
2087
- ) from exc
2088
- if completed.returncode not in {0, 1}:
2089
- raise ToolExecutionError(
2090
- "search_failed",
2091
- "ripgrep search failed",
2092
- details={"returncode": completed.returncode, "stderr": completed.stderr.strip()},
2093
- )
2094
- return completed
2095
-
2096
- @staticmethod
2097
- def _normalize_existing_dir(path_value: str | None) -> Path | None:
2098
- if not str(path_value or "").strip():
2099
- return None
2100
- candidate = Path(str(path_value).strip()).expanduser().resolve()
2101
- if not candidate.exists() or not candidate.is_dir():
2102
- return None
2103
- return candidate
2104
-
2105
- def _iter_code_pack_candidate_paths(self, *, repo_root: Path) -> list[Path]:
2106
- candidates: list[Path] = []
2107
- explicit_pack_path = str(self._code_evidence_pack_path or "").strip()
2108
- if explicit_pack_path:
2109
- candidates.append(Path(explicit_pack_path).expanduser())
2110
-
2111
- env_pack_path = str(os.getenv("VDS_AUDIT_CODE_EVIDENCE_PACK_PATH") or "").strip()
2112
- if env_pack_path:
2113
- candidates.append(Path(env_pack_path).expanduser())
2114
-
2115
- candidates.append(repo_root / "evidence" / "code" / "code_evidence_pack.json")
2116
- candidates.append(repo_root.parent / "evidence" / "code" / "code_evidence_pack.json")
2117
-
2118
- unique_candidates: list[Path] = []
2119
- seen: set[str] = set()
2120
- for candidate in candidates:
2121
- try:
2122
- resolved = candidate.resolve()
2123
- except Exception:
2124
- continue
2125
- marker = str(resolved)
2126
- if marker in seen:
2127
- continue
2128
- seen.add(marker)
2129
- unique_candidates.append(resolved)
2130
- return unique_candidates
2131
-
2132
- def _load_code_evidence_pack(self, *, repo_root: Path) -> CodeEvidencePack | None:
2133
- if self._code_evidence_pack_cache is not self._UNSET:
2134
- return (
2135
- self._code_evidence_pack_cache if isinstance(self._code_evidence_pack_cache, CodeEvidencePack) else None
2136
- )
2137
-
2138
- self._code_evidence_pack_cache = None
2139
- for candidate in self._iter_code_pack_candidate_paths(repo_root=repo_root):
2140
- if not candidate.exists() or not candidate.is_file():
2141
- continue
2142
- try:
2143
- self._code_evidence_pack_cache = CodeEvidencePack.load(candidate)
2144
- break
2145
- except Exception:
2146
- continue
2147
- return self._code_evidence_pack_cache if isinstance(self._code_evidence_pack_cache, CodeEvidencePack) else None
2148
-
2149
- def _resolve_env_config_root(self, *, repo_root: Path) -> Path | None:
2150
- direct_root = self._normalize_existing_dir(str(os.getenv("VDS_AUDIT_CONFIG_ROOT") or "").strip())
2151
- if direct_root is not None:
2152
- return direct_root
2153
-
2154
- app_config_root_value = str(os.getenv("VDS_AUDIT_APP_CONFIG_PATH") or "").strip()
2155
- app_config_root = self._normalize_existing_dir(app_config_root_value)
2156
- if app_config_root is None:
2157
- return None
2158
-
2159
- try:
2160
- resolution = CodePackBuilder.resolve_config_path(app_config_root, repo_root.name)
2161
- except Exception:
2162
- resolution = None
2163
- if resolution is not None and resolution.matched and str(resolution.config_path or "").strip():
2164
- matched_root = self._normalize_existing_dir(str(resolution.config_path))
2165
- if matched_root is not None:
2166
- return matched_root
2167
- return app_config_root
2168
-
2169
- @staticmethod
2170
- def _dedupe_paths(paths: list[Path]) -> list[Path]:
2171
- deduped: list[Path] = []
2172
- seen: set[str] = set()
2173
- for path in paths:
2174
- marker = str(path.resolve())
2175
- if marker in seen:
2176
- continue
2177
- seen.add(marker)
2178
- deduped.append(path)
2179
- return deduped
2180
-
2181
- @staticmethod
2182
- def _derive_project_parent(repo_root: Path) -> Path | None:
2183
- """Derive the project-level parent directory from repo cache convention.
2184
-
2185
- Convention: ``<effective-cache-root>/repos/<BB_PROJECT>-project/<repo>/``
2186
- Returns the ``<BB_PROJECT>-project/`` directory when the convention
2187
- matches, or ``None`` when the repo root does not follow the convention.
2188
- """
2189
- parent = repo_root.parent
2190
- if parent.name.endswith("-project"):
2191
- return parent
2192
- return None
2193
-
2194
- @staticmethod
2195
- def _discover_same_project_roots(*, repo_root: Path, target_role: RepoRole) -> list[Path]:
2196
- """Discover sibling repos under the same ``<BB_PROJECT>-project/`` parent with the given role.
2197
-
2198
- Uses the repo cache convention ``<effective-cache-root>/repos/<BB_PROJECT>-project/<repo>/``
2199
- and deterministic ``classify_repo_role()`` to find same-project lib or config repos
2200
- (DD-123.10, DD-123.12).
2201
- """
2202
- project_parent = repo_root.parent
2203
- if not project_parent.name.endswith("-project"):
2204
- return []
2205
- if not project_parent.is_dir():
2206
- return []
2207
-
2208
- repo_name = repo_root.name
2209
- discovered: list[Path] = []
2210
- try:
2211
- siblings = sorted(project_parent.iterdir())
2212
- except OSError:
2213
- return []
2214
-
2215
- for sibling in siblings:
2216
- if not sibling.is_dir() or sibling.name.startswith("."):
2217
- continue
2218
- if sibling.name == repo_name:
2219
- continue
2220
- role = classify_repo_role(repo_key=sibling.name, repo_path=sibling)
2221
- if role == target_role:
2222
- discovered.append(sibling.resolve(strict=False))
2223
-
2224
- if discovered:
2225
- _log.info(
2226
- "same_project_roots_discovered",
2227
- target_role=str(target_role),
2228
- project_parent=str(project_parent),
2229
- discovered=[d.name for d in discovered],
2230
- )
2231
- return discovered
2232
-
2233
- @classmethod
2234
- def _filter_repo_scoped_paths(
2235
- cls,
2236
- *,
2237
- repo_root: Path,
2238
- candidates: list[Path],
2239
- allow_same_project: bool = False,
2240
- ) -> list[Path]:
2241
- """Keep only roots that are inside the active repository root.
2242
-
2243
- When *allow_same_project* is True, also accept roots that share the
2244
- same project-level parent directory (DD-123.11). This enables
2245
- same-project sibling repos (e.g. ``CEP-project/campaign-common-lib/``)
2246
- to remain reachable while still blocking truly external paths.
2247
- """
2248
- project_parent: Path | None = None
2249
- if allow_same_project:
2250
- project_parent = cls._derive_project_parent(repo_root)
2251
-
2252
- scoped: list[Path] = []
2253
- for candidate in candidates:
2254
- resolved_candidate = candidate.resolve(strict=False)
2255
- # Fast path: candidate is inside repo_root.
2256
- try:
2257
- resolved_candidate.relative_to(repo_root)
2258
- scoped.append(resolved_candidate)
2259
- continue
2260
- except ValueError:
2261
- pass
2262
- # Slow path: candidate shares the same project-level parent.
2263
- if project_parent is not None:
2264
- try:
2265
- resolved_candidate.relative_to(project_parent)
2266
- scoped.append(resolved_candidate)
2267
- continue
2268
- except ValueError:
2269
- pass
2270
- return scoped
2271
-
2272
- def _resolve_config_roots(self, *, repo_root: Path) -> list[Path]:
2273
- roots: list[Path] = []
2274
- trusted_external_roots: list[Path] = []
2275
- explicit_root = self._normalize_existing_dir(self._config_root)
2276
- if explicit_root is not None:
2277
- roots.append(explicit_root)
2278
- trusted_external_roots.append(explicit_root)
2279
-
2280
- env_root = self._resolve_env_config_root(repo_root=repo_root)
2281
- if env_root is not None:
2282
- roots.append(env_root)
2283
- trusted_external_roots.append(env_root)
2284
-
2285
- pack = self._load_code_evidence_pack(repo_root=repo_root)
2286
- if pack is not None and pack.config_pack is not None:
2287
- pack_root = self._normalize_existing_dir(str(pack.config_pack.config_root or "").strip())
2288
- if pack_root is not None:
2289
- roots.append(pack_root)
2290
- trusted_external_roots.append(pack_root)
2291
-
2292
- # Tier 3: DOPS/app-config fallback under the effective VDS cache root.
2293
- cache_root = get_vds_cache_root()
2294
- for dops_key in ("DOPS-project", "dops-project"):
2295
- dops_app_config = cache_root / "repos" / dops_key / "app-config"
2296
- if dops_app_config.is_dir():
2297
- roots.append(dops_app_config.resolve(strict=False))
2298
- dops_root = cache_root / "repos" / dops_key
2299
- if dops_root.is_dir():
2300
- roots.append(dops_root.resolve(strict=False))
2301
-
2302
- # Phase 123 (TSK-123.6, DD-123.12): same-project sibling repos with RepoRole.CONFIG.
2303
- roots.extend(self._discover_same_project_roots(repo_root=repo_root, target_role=RepoRole.CONFIG))
2304
-
2305
- scoped_roots = self._filter_repo_scoped_paths(
2306
- repo_root=repo_root.resolve(strict=False),
2307
- candidates=self._dedupe_paths(roots),
2308
- allow_same_project=True,
2309
- )
2310
- # Keep explicit/env/pack-discovered config roots even when they live
2311
- # outside the active project cache (for example DOPS/app-config).
2312
- return self._dedupe_paths([*trusted_external_roots, *scoped_roots])
2313
-
2314
- def _resolve_env_lib_roots(self) -> list[Path]:
2315
- raw = str(os.getenv("VDS_AUDIT_LIB_ROOTS") or "").strip()
2316
- if not raw:
2317
- return []
2318
- roots: list[Path] = []
2319
- for token in re.split(r"[,\n]", raw):
2320
- path_value = token.strip()
2321
- if not path_value:
2322
- continue
2323
- root = self._normalize_existing_dir(path_value)
2324
- if root is not None:
2325
- roots.append(root)
2326
- return roots
2327
-
2328
- def _resolve_lib_roots(self, *, repo_root: Path) -> list[tuple[str, Path]]:
2329
- roots: list[Path] = []
2330
- for path_value in self._lib_roots:
2331
- normalized = self._normalize_existing_dir(path_value)
2332
- if normalized is not None:
2333
- roots.append(normalized)
2334
- roots.extend(self._resolve_env_lib_roots())
2335
-
2336
- pack = self._load_code_evidence_pack(repo_root=repo_root)
2337
- if pack is not None and pack.lib_pack is not None:
2338
- for pack_root in pack.lib_pack.lib_roots:
2339
- normalized = self._normalize_existing_dir(str(pack_root or "").strip())
2340
- if normalized is not None:
2341
- roots.append(normalized)
2342
-
2343
- # Phase 123 (TSK-123.5, DD-123.12): Tier 3 — same-project sibling repos with RepoRole.LIB.
2344
- roots.extend(self._discover_same_project_roots(repo_root=repo_root, target_role=RepoRole.LIB))
2345
-
2346
- scoped_roots = self._filter_repo_scoped_paths(
2347
- repo_root=repo_root.resolve(strict=False),
2348
- candidates=self._dedupe_paths(roots),
2349
- allow_same_project=True,
2350
- )
2351
- deduped_roots = self._dedupe_paths(scoped_roots)
2352
- if not deduped_roots:
2353
- return []
2354
-
2355
- named_roots: list[tuple[str, Path]] = []
2356
- name_counts: dict[str, int] = {}
2357
- for root in deduped_roots:
2358
- base_name = root.name or "lib"
2359
- index = name_counts.get(base_name, 0) + 1
2360
- name_counts[base_name] = index
2361
- slug = base_name if index == 1 else f"{base_name}-{index}"
2362
- named_roots.append((slug, root))
2363
- return named_roots
2364
-
2365
- def _build_code_search_queries(self, query: str) -> list[str]:
2366
- normalized = str(query or "").strip()
2367
- if not normalized:
2368
- return []
2369
- queries: list[str] = []
2370
- normalized_seen: set[str] = set()
2371
-
2372
- def _append_unique(candidate: str) -> None:
2373
- value = str(candidate or "").strip()
2374
- if not value:
2375
- return
2376
- key = value.lower()
2377
- if key in normalized_seen:
2378
- return
2379
- normalized_seen.add(key)
2380
- queries.append(value)
2381
-
2382
- _append_unique(normalized)
2383
- dependency_query = self._is_project_scope_dependency_query(normalized)
2384
-
2385
- # Security scan requirements often include generic severity words
2386
- # ("high"/"critical"), which produce noisy grep matches. Keep focused
2387
- # scan tokens and add stable recovery probes for scan artifacts.
2388
- if self._is_security_scan_query(normalized):
2389
- for term in self._extract_query_terms(normalized):
2390
- if self._is_generic_security_severity_term(term):
2391
- continue
2392
- _append_unique(term)
2393
- for recovery_query in (
2394
- "sast dast security scan",
2395
- "vulnerability scan report",
2396
- "sonarqube trivy snyk zap",
2397
- ):
2398
- _append_unique(recovery_query)
2399
- return queries[:7]
2400
-
2401
- if dependency_query:
2402
- for term in self._PROJECT_SCOPE_DEPENDENCY_QUERY_EXPANSION:
2403
- _append_unique(term)
2404
- for term in self._extract_query_terms(normalized):
2405
- _append_unique(term)
2406
- if dependency_query:
2407
- return queries[:10]
2408
- if self._is_db_decoupling_query(normalized):
2409
- for term in self._DB_RETRIEVAL_QUERY_EXPANSION:
2410
- _append_unique(term)
2411
- _append_unique("datasource entitymanager nativequery")
2412
- _append_unique("repository schema hibernate")
2413
- return queries[:12]
2414
- return queries[:7]
2415
-
2416
- @classmethod
2417
- def _code_path_relevance_bonus(cls, *, path_value: str, query: str) -> float:
2418
- path_lower = cls._normalize_path_for_scoring(path_value)
2419
- query_lower = str(query or "").lower()
2420
- observability_terms = ("log", "logger", "audit", "monitor", "metric", "trace", "telemetry")
2421
- low_signal_terms = ("constant", "constants", "util", "utils", "dto", "entity", "model", "vo")
2422
- bonus = 0.0
2423
- if cls._is_doc_like_path(path_lower):
2424
- bonus -= 0.25
2425
- if any(token in query_lower for token in observability_terms):
2426
- if any(token in path_lower for token in observability_terms):
2427
- bonus += 0.20
2428
- if any(token in path_lower for token in low_signal_terms):
2429
- bonus -= 0.12
2430
- if cls._is_business_control_query(query_lower):
2431
- domain_bonus, has_domain_alignment = cls._business_control_domain_alignment(
2432
- path_lower=path_lower,
2433
- query_lower=query_lower,
2434
- )
2435
- bonus += domain_bonus
2436
- bonus += cls._business_control_low_signal_penalty(
2437
- path_lower=path_lower,
2438
- has_domain_alignment=has_domain_alignment,
2439
- )
2440
- if cls._is_db_decoupling_query(query_lower):
2441
- if any(
2442
- hint in path_lower
2443
- for hint in (
2444
- "/config/database",
2445
- "/repository/",
2446
- "repository",
2447
- "databaseconfig",
2448
- "datasource",
2449
- "entitymanager",
2450
- "jdbctemplate",
2451
- "nativequery",
2452
- )
2453
- ):
2454
- bonus += 0.28
2455
- if any(hint in path_lower for hint in ("/service/", "/impl/", "serviceimpl", "service/impl")):
2456
- bonus -= 0.18
2457
- return bonus
2458
-
2459
- @staticmethod
2460
- def _is_doc_like_path(path_value: str) -> bool:
2461
- normalized = str(path_value or "").lower().replace("\\", "/")
2462
- return bool(re.search(r"\.(md|markdown|rst|adoc|txt)$", normalized) or "/docs/" in f"/{normalized}")
2463
-
2464
- @staticmethod
2465
- def _normalize_path_for_scoring(path_value: str) -> str:
2466
- normalized = str(path_value or "").strip().lower().replace("\\", "/")
2467
- if not normalized:
2468
- return "/"
2469
- return normalized if normalized.startswith("/") else f"/{normalized}"
2470
-
2471
- @classmethod
2472
- def _is_business_control_query(cls, query: str) -> bool:
2473
- normalized = str(query or "").strip().lower()
2474
- if not normalized:
2475
- return False
2476
- return any(
2477
- token in normalized for tokens in cls._BUSINESS_CONTROL_DOMAIN_TOKEN_GROUPS.values() for token in tokens
2478
- )
2479
-
2480
- @classmethod
2481
- def _business_control_domain_alignment(cls, *, path_lower: str, query_lower: str) -> tuple[float, bool]:
2482
- aligned_groups = 0
2483
- bonus = 0.0
2484
- for tokens in cls._BUSINESS_CONTROL_DOMAIN_TOKEN_GROUPS.values():
2485
- if not any(token in query_lower for token in tokens):
2486
- continue
2487
- if any(token in path_lower for token in tokens):
2488
- aligned_groups += 1
2489
- bonus += 0.08
2490
- if aligned_groups >= 2:
2491
- bonus += 0.03
2492
- return min(0.27, bonus), aligned_groups > 0
2493
-
2494
- @classmethod
2495
- def _business_control_low_signal_penalty(cls, *, path_lower: str, has_domain_alignment: bool) -> float:
2496
- penalty = 0.0
2497
- if any(token in path_lower for token in cls._BUSINESS_CONTROL_INTERNAL_PATH_HINTS):
2498
- penalty -= 0.22
2499
- if any(token in path_lower for token in cls._BUSINESS_CONTROL_TEST_PATH_HINTS):
2500
- penalty -= 0.20
2501
- if cls._has_hidden_dotfile_segment(path_lower):
2502
- penalty -= 0.16
2503
- if not has_domain_alignment and any(
2504
- token in path_lower for token in cls._BUSINESS_CONTROL_LOW_SIGNAL_PATH_HINTS
2505
- ):
2506
- penalty -= 0.12
2507
- return penalty
2508
-
2509
- @classmethod
2510
- def _is_alerting_channel_query(cls, query: str) -> bool:
2511
- normalized = str(query or "").strip().lower()
2512
- if not normalized:
2513
- return False
2514
- has_channel_signal = any(token in normalized for token in cls._ALERTING_CHANNEL_TERMS)
2515
- has_intent_signal = any(token in normalized for token in cls._ALERTING_INTENT_TERMS)
2516
- return has_channel_signal and has_intent_signal
2517
-
2518
- @classmethod
2519
- def _is_security_scan_query(cls, query: str) -> bool:
2520
- normalized = str(query or "").strip().lower()
2521
- if not normalized:
2522
- return False
2523
- if any(token in normalized for token in cls._SECURITY_SCAN_QUERY_TERMS):
2524
- return True
2525
- return "high" in normalized and "critical" in normalized and "security" in normalized
2526
-
2527
- @classmethod
2528
- def _is_generic_security_severity_term(cls, term: str) -> bool:
2529
- normalized = str(term or "").strip().lower()
2530
- if not normalized:
2531
- return False
2532
- return normalized in cls._SECURITY_SCAN_GENERIC_SEVERITY_TERMS
2533
-
2534
- @classmethod
2535
- def _is_security_scan_semantic_match(cls, *, path_value: str, excerpt: str) -> bool:
2536
- path_lower = cls._normalize_path_for_scoring(path_value)
2537
- haystack = f"{path_lower} {excerpt}".lower()
2538
- if any(token in haystack for token in cls._SECURITY_SCAN_SEMANTIC_TERMS):
2539
- return True
2540
- if any(token in path_lower for token in cls._SECURITY_SCAN_PATH_HINTS):
2541
- return True
2542
- has_severity_only_signal = any(token in haystack for token in ("high", "critical")) and not any(
2543
- token in haystack
2544
- for token in (
2545
- "sast",
2546
- "dast",
2547
- "scan",
2548
- "vulnerability",
2549
- "security",
2550
- "sonar",
2551
- "trivy",
2552
- "snyk",
2553
- "zap",
2554
- "cve",
2555
- )
2556
- )
2557
- if has_severity_only_signal:
2558
- return False
2559
- return False
2560
-
2561
- @classmethod
2562
- def _is_alerting_semantic_match(cls, *, path_value: str, excerpt: str) -> bool:
2563
- haystack = f"{path_value} {excerpt}".lower()
2564
- has_channel_signal = any(token in haystack for token in cls._ALERTING_CHANNEL_TERMS)
2565
- has_intent_signal = any(token in haystack for token in cls._ALERTING_INTENT_TERMS)
2566
- return has_channel_signal and has_intent_signal
2567
-
2568
- @classmethod
2569
- def _is_alerting_false_positive_match(cls, *, path_value: str, excerpt: str) -> bool:
2570
- haystack = f"{path_value} {excerpt}".lower()
2571
- if not any(pattern in haystack for pattern in cls._ALERTING_FALSE_POSITIVE_SNIPPETS):
2572
- return False
2573
- # Keep genuine alerting hits that explicitly include alerting intent even
2574
- # when they contain an ambiguous token like "slack".
2575
- return not any(token in haystack for token in cls._ALERTING_INTENT_TERMS)
2576
-
2577
- @staticmethod
2578
- def _has_hidden_dotfile_segment(path_lower: str) -> bool:
2579
- segments = [segment for segment in str(path_lower or "").split("/") if segment not in {"", ".", ".."}]
2580
- return any(segment.startswith(".") for segment in segments)
2581
-
2582
- def _read_doc_chunk(self, request: ReadDocChunkInput) -> ReadDocChunkOutput:
2583
- if not self._state_dsn or not self._project_key:
2584
- raise ToolExecutionError(
2585
- "missing_runtime_context",
2586
- "read_doc_chunk requires state_dsn and project_key",
2587
- details={"required": ["state_dsn", "project_key"]},
2588
- )
2589
-
2590
- candidates = self._extract_doc_ref_candidates(request.ref)
2591
- chunk_id = (request.chunk_id or candidates.get("chunk_id") or "").strip() or None
2592
- source_uri = candidates.get("source_uri")
2593
- document_id = candidates.get("document_id")
2594
-
2595
- if chunk_id is None and source_uri is None and document_id is None:
2596
- raise ToolExecutionError(
2597
- "invalid_doc_ref",
2598
- "read_doc_chunk requires chunk_id or ref with source_uri/document_id",
2599
- details={"ref": request.ref},
2600
- )
2601
-
2602
- row = self._lookup_doc_chunk(
2603
- chunk_id=chunk_id,
2604
- source_uri=source_uri,
2605
- document_id=document_id,
2606
- repo_key=self._repo_key,
2607
- )
2608
- if row is None and self._repo_key:
2609
- row = self._lookup_doc_chunk(
2610
- chunk_id=chunk_id,
2611
- source_uri=source_uri,
2612
- document_id=document_id,
2613
- repo_key=None,
2614
- )
2615
- if row is None:
2616
- raise ToolExecutionError(
2617
- "doc_chunk_not_found",
2618
- "Document chunk not found in scoped state",
2619
- details={
2620
- "project_key": self._project_key,
2621
- "repo_key": self._repo_key,
2622
- "chunk_id": chunk_id,
2623
- "source_uri": source_uri,
2624
- "document_id": document_id,
2625
- },
2626
- )
2627
- if self._is_excluded_docs_artifact(
2628
- source_uri=str(row.get("source_uri") or "").strip() or None,
2629
- document_id=str(row.get("document_id") or "").strip() or None,
2630
- source_type=str(row.get("source_type") or "").strip() or None,
2631
- metadata=row.get("document_metadata"),
2632
- ):
2633
- raise ToolExecutionError(
2634
- "doc_chunk_excluded",
2635
- "Requested document chunk is excluded from docs evidence scope",
2636
- details={
2637
- "project_key": self._project_key,
2638
- "repo_key": self._repo_key,
2639
- "chunk_id": str(row.get("chunk_id") or chunk_id or ""),
2640
- "source_uri": str(row.get("source_uri") or source_uri or ""),
2641
- "document_id": str(row.get("document_id") or document_id or ""),
2642
- },
2643
- )
2644
-
2645
- resolved_chunk_id = str(row.get("chunk_id") or chunk_id or "").strip()
2646
- resolved_ref = f"chunk:{resolved_chunk_id}" if resolved_chunk_id else str(request.ref)
2647
- return ReadDocChunkOutput(
2648
- ref=resolved_ref,
2649
- chunk_id=resolved_chunk_id or None,
2650
- content=str(row.get("content_text") or ""),
2651
- page_id=str(row.get("page_id") or "").strip() or None,
2652
- page_title=_extract_page_title(row.get("document_metadata")),
2653
- source_url=str(row.get("source_uri") or "").strip() or None,
2654
- space_key=_extract_space_key(row.get("document_metadata")),
2655
- )
2656
-
2657
- def _read_code_file(self, request: ReadCodeFileInput) -> ReadCodeFileOutput:
2658
- repo_root = self._resolve_repo_root(require_exists=True)
2659
- prefixed_scope, normalized_path, inferred_line = self._extract_scoped_code_path(request.path)
2660
- effective_scope: Literal["code", "config", "lib"] = "code"
2661
- resolved_any_scope: tuple[Literal["code", "config", "lib"], Path, str] | None = None
2662
- if request.scope == "all":
2663
- effective_scope = prefixed_scope or "code"
2664
- if prefixed_scope is None:
2665
- resolved_any_scope = self._resolve_all_scope_code_path(
2666
- repo_root=repo_root,
2667
- path_value=normalized_path,
2668
- config_root_filter=request.config_root_filter,
2669
- )
2670
- if resolved_any_scope is not None:
2671
- effective_scope, target_file, output_path = resolved_any_scope
2672
- elif prefixed_scope is not None and prefixed_scope != request.scope:
2673
- raise ToolExecutionError(
2674
- "scope_path_mismatch",
2675
- "Requested path scope prefix does not match scope parameter",
2676
- details={"path": request.path, "scope": request.scope, "prefixed_scope": prefixed_scope},
2677
- )
2678
- else:
2679
- effective_scope = request.scope
2680
-
2681
- if resolved_any_scope is None and effective_scope == "code":
2682
- target_file = self._resolve_repo_file(repo_root=repo_root, path_value=normalized_path)
2683
- output_path = target_file.relative_to(repo_root).as_posix()
2684
- elif resolved_any_scope is None and effective_scope == "config":
2685
- config_roots = self._filter_config_roots(
2686
- self._resolve_config_roots(repo_root=repo_root),
2687
- config_root_filter=request.config_root_filter,
2688
- )
2689
- if not config_roots:
2690
- raise ToolExecutionError(
2691
- "code_file_not_found",
2692
- "Requested code file does not exist",
2693
- details={"path": request.path, "scope": effective_scope},
2694
- )
2695
- named_roots = [(root.name or "config", root) for root in config_roots]
2696
- target_file, output_path = self._resolve_file_from_named_roots(
2697
- named_roots=named_roots,
2698
- path_value=normalized_path,
2699
- scope=effective_scope,
2700
- )
2701
- elif resolved_any_scope is None:
2702
- lib_roots = self._resolve_lib_roots(repo_root=repo_root)
2703
- if not lib_roots:
2704
- raise ToolExecutionError(
2705
- "code_file_not_found",
2706
- "Requested code file does not exist",
2707
- details={"path": request.path, "scope": effective_scope},
2708
- )
2709
- target_file, output_path = self._resolve_file_from_named_roots(
2710
- named_roots=lib_roots,
2711
- path_value=normalized_path,
2712
- scope=effective_scope,
2713
- )
2714
-
2715
- if request.start_line is not None and request.end_line is not None and request.end_line < request.start_line:
2716
- raise ToolExecutionError(
2717
- "invalid_line_range",
2718
- "end_line must be greater than or equal to start_line",
2719
- details={"start_line": request.start_line, "end_line": request.end_line},
2720
- )
2721
- if not target_file.is_file():
2722
- raise ToolExecutionError(
2723
- "code_file_not_found",
2724
- "Requested code file does not exist",
2725
- details={"path": request.path},
2726
- )
2727
-
2728
- file_text = target_file.read_text(encoding="utf-8", errors="replace")
2729
- all_lines = file_text.splitlines()
2730
- effective_start_line = request.start_line
2731
- effective_end_line = request.end_line
2732
- if effective_start_line is None and effective_end_line is None and inferred_line is not None:
2733
- effective_start_line = max(1, inferred_line - self._CODE_AUTO_READ_WINDOW_RADIUS)
2734
- effective_end_line = min(len(all_lines), inferred_line + self._CODE_AUTO_READ_WINDOW_RADIUS)
2735
-
2736
- start_index = (effective_start_line - 1) if effective_start_line is not None else 0
2737
- end_index = effective_end_line if effective_end_line is not None else len(all_lines)
2738
- sliced_lines = all_lines[start_index:end_index]
2739
- content = "\n".join(sliced_lines)
2740
-
2741
- output_ref = output_path
2742
- if inferred_line is not None:
2743
- output_ref = f"{output_path}:{inferred_line}"
2744
-
2745
- return ReadCodeFileOutput(
2746
- path=output_ref,
2747
- content=content,
2748
- start_line=effective_start_line,
2749
- end_line=effective_end_line,
2750
- )
2751
-
2752
- def _resolve_all_scope_code_path(
2753
- self,
2754
- *,
2755
- repo_root: Path,
2756
- path_value: str,
2757
- config_root_filter: str | None = None,
2758
- ) -> tuple[Literal["code", "config", "lib"], Path, str] | None:
2759
- normalized = str(path_value or "").strip()
2760
- if not normalized:
2761
- return None
2762
-
2763
- target_file = self._resolve_repo_file(repo_root=repo_root, path_value=normalized)
2764
- if target_file.is_file():
2765
- return "code", target_file, target_file.relative_to(repo_root).as_posix()
2766
-
2767
- lib_roots = self._resolve_lib_roots(repo_root=repo_root)
2768
- if lib_roots:
2769
- try:
2770
- target_file, output_path = self._resolve_file_from_named_roots(
2771
- named_roots=lib_roots,
2772
- path_value=normalized,
2773
- scope="lib",
2774
- )
2775
- return "lib", target_file, output_path
2776
- except ToolExecutionError:
2777
- pass
2778
-
2779
- config_roots = self._filter_config_roots(
2780
- self._resolve_config_roots(repo_root=repo_root),
2781
- config_root_filter=config_root_filter,
2782
- )
2783
- if config_roots:
2784
- named_roots = [(root.name or "config", root) for root in config_roots]
2785
- try:
2786
- target_file, output_path = self._resolve_file_from_named_roots(
2787
- named_roots=named_roots,
2788
- path_value=normalized,
2789
- scope="config",
2790
- )
2791
- return "config", target_file, output_path
2792
- except ToolExecutionError:
2793
- pass
2794
-
2795
- return None
2796
-
2797
- @staticmethod
2798
- def _extract_scoped_code_path(path_value: str) -> tuple[Literal["code", "config", "lib"] | None, str, int | None]:
2799
- normalized = str(path_value or "").strip()
2800
- if not normalized:
2801
- return None, "", None
2802
- prefix, separator, remainder = normalized.partition(":")
2803
- if separator != ":" or prefix not in {"code", "config", "lib"}:
2804
- scoped_path, inferred_line = ToolRegistry._extract_line_hint(normalized)
2805
- return None, scoped_path, inferred_line
2806
- scoped_path, inferred_line = ToolRegistry._extract_line_hint(remainder.strip())
2807
- return cast("Literal['code', 'config', 'lib']", prefix), scoped_path, inferred_line
2808
-
2809
- @staticmethod
2810
- def _extract_line_hint(path_value: str) -> tuple[str, int | None]:
2811
- normalized = str(path_value or "").strip()
2812
- if ":" not in normalized:
2813
- return normalized, None
2814
- maybe_path, maybe_line = normalized.rsplit(":", 1)
2815
- if maybe_line.isdigit() and maybe_path.strip():
2816
- line_number = int(maybe_line)
2817
- if line_number >= 1:
2818
- return maybe_path.strip(), line_number
2819
- return normalized, None
2820
-
2821
- def _resolve_file_from_named_roots(
2822
- self,
2823
- *,
2824
- named_roots: list[tuple[str, Path]],
2825
- path_value: str,
2826
- scope: Literal["config", "lib"],
2827
- ) -> tuple[Path, str]:
2828
- normalized = str(path_value or "").strip().replace("\\", "/")
2829
- if not normalized:
2830
- raise ToolExecutionError(
2831
- "invalid_code_path",
2832
- "Requested code path is empty",
2833
- details={"path": path_value, "scope": scope},
2834
- )
2835
-
2836
- root_map = dict(named_roots)
2837
- root_name, separator, remainder = normalized.partition("/")
2838
- preferred_root: tuple[str, Path] | None = None
2839
- relative_path = normalized
2840
- if separator and root_name in root_map:
2841
- preferred_root = (root_name, root_map[root_name])
2842
- relative_path = remainder
2843
-
2844
- if scope == "lib" and preferred_root is None:
2845
- raise ToolExecutionError(
2846
- "invalid_code_path",
2847
- "Lib scope path must be prefixed with '<repo-slug>/'",
2848
- details={
2849
- "path": path_value,
2850
- "scope": scope,
2851
- "required_prefixes": sorted(root_map),
2852
- },
2853
- )
2854
-
2855
- candidate_roots = [preferred_root] if preferred_root is not None else named_roots
2856
- for candidate in candidate_roots:
2857
- assert candidate is not None
2858
- root_label, root_path = candidate
2859
- target_file = self._resolve_repo_file(repo_root=root_path, path_value=relative_path)
2860
- if not target_file.is_file():
2861
- continue
2862
- relative = target_file.relative_to(root_path).as_posix()
2863
- display_path = relative if scope == "config" else f"{root_label}/{relative}"
2864
- return target_file, display_path
2865
-
2866
- raise ToolExecutionError(
2867
- "code_file_not_found",
2868
- "Requested code file does not exist",
2869
- details={
2870
- "path": path_value,
2871
- "scope": scope,
2872
- "roots": [name for name, _root in named_roots],
2873
- },
2874
- )
2875
-
2876
- def _get_row_context(self, request: GetRowContextInput) -> GetRowContextOutput:
2877
- # Returns normalized row context for loop planners.
2878
- return GetRowContextOutput(
2879
- row_id=request.row_id,
2880
- context={
2881
- "check_id": request.check_id,
2882
- "requirement_text": request.requirement_text,
2883
- "requirement_category": request.requirement_category,
2884
- "detailed_guidance": request.detailed_guidance,
2885
- "check_manual": request.check_manual,
2886
- "seed_evidence_ref_count": len(request.evidence_refs),
2887
- },
2888
- )
2889
-
2890
- def _record_evidence_refs(self, request: RecordEvidenceRefsInput) -> RecordEvidenceRefsOutput:
2891
- existing = self._evidence_store.get(request.row_id, [])
2892
- seen = {(ref.ref_type, ref.ref_value) for ref in existing}
2893
- accepted = list(existing)
2894
-
2895
- for ref in request.refs:
2896
- key = (ref.ref_type, ref.ref_value)
2897
- if key in seen:
2898
- continue
2899
- accepted.append(ref)
2900
- seen.add(key)
2901
-
2902
- self._evidence_store[request.row_id] = accepted
2903
- return RecordEvidenceRefsOutput(
2904
- row_id=request.row_id,
2905
- accepted_count=len(accepted),
2906
- refs=accepted,
2907
- )
2908
-
2909
- @staticmethod
2910
- def _record_skill_tool_usage(entry: dict[str, Any]) -> None:
2911
- try:
2912
- from vds_agent_core.skills.executor import SkillExecutor
2913
-
2914
- SkillExecutor.record_tool_usage(dict(entry))
2915
- except Exception:
2916
- return
2917
-
2918
- @staticmethod
2919
- def _normalize_skill_identifier(value: str) -> str:
2920
- normalized = str(value or "").strip().lower()
2921
- if not normalized:
2922
- return ""
2923
- normalized = re.sub(r"[\s_]+", "-", normalized)
2924
- normalized = re.sub(r"-{2,}", "-", normalized)
2925
- return normalized
2926
-
2927
- @classmethod
2928
- def _build_skill_aliases(cls, *values: str | None) -> set[str]:
2929
- aliases: set[str] = set()
2930
- for value in values:
2931
- text = str(value or "").strip()
2932
- if not text:
2933
- continue
2934
- aliases.add(text)
2935
- normalized = cls._normalize_skill_identifier(text)
2936
- if normalized:
2937
- aliases.add(normalized)
2938
- return aliases
2939
-
2940
- def _resolve_skills_runtime_policy(self) -> dict[str, Any]:
2941
- def _normalize_skill_directories(raw_directories: list[str]) -> list[str]:
2942
- normalized: list[str] = []
2943
- seen: set[str] = set()
2944
- for raw_path in raw_directories:
2945
- value = str(raw_path).strip()
2946
- if not value:
2947
- continue
2948
- try:
2949
- resolved = str(Path(value).expanduser().resolve(strict=False))
2950
- except Exception:
2951
- resolved = value
2952
- if resolved in seen:
2953
- continue
2954
- seen.add(resolved)
2955
- if Path(resolved).is_dir():
2956
- normalized.append(resolved)
2957
- return normalized
2958
-
2959
- def _env_bool(name: str) -> tuple[bool, bool]:
2960
- raw = os.getenv(name)
2961
- if raw is None:
2962
- return (False, False)
2963
- normalized = str(raw).strip().lower()
2964
- return (True, normalized in {"true", "1", "yes", "on"})
2965
-
2966
- def _env_list(name: str) -> tuple[bool, list[str]]:
2967
- raw = os.getenv(name)
2968
- if raw is None:
2969
- return (False, [])
2970
- value = str(raw).strip()
2971
- if not value:
2972
- return (True, [])
2973
- if value.startswith("["):
2974
- try:
2975
- parsed = json.loads(value)
2976
- except json.JSONDecodeError:
2977
- return (True, [])
2978
- if isinstance(parsed, list):
2979
- return (True, [str(item).strip() for item in parsed if str(item).strip()])
2980
- return (True, [])
2981
- return (True, [item.strip() for item in value.split(",") if item.strip()])
2982
-
2983
- def _env_trust_tier_map(name: str) -> tuple[bool, dict[str, str]]:
2984
- raw = os.getenv(name)
2985
- if raw is None:
2986
- return (False, {})
2987
- value = str(raw).strip()
2988
- if not value:
2989
- return (True, {})
2990
- try:
2991
- parsed = json.loads(value)
2992
- except json.JSONDecodeError:
2993
- return (True, {})
2994
- if not isinstance(parsed, dict):
2995
- return (True, {})
2996
- validated: dict[str, str] = {}
2997
- for raw_name, raw_tier in parsed.items():
2998
- normalized_name = self._normalize_skill_identifier(str(raw_name))
2999
- tier = str(raw_tier).strip()
3000
- if normalized_name and tier:
3001
- validated[normalized_name] = tier
3002
- return (True, validated)
3003
-
3004
- defaults = {
3005
- "enabled": False,
3006
- "directories": [],
3007
- "allowlist": [],
3008
- "allowed_trust_tiers": [],
3009
- "default_trust_tier": "external-unverified",
3010
- "trust_tiers": {},
3011
- "allow_script_execution": False,
3012
- }
3013
- enabled_present, enabled_env = _env_bool("VDS_AUDIT_LLM__SKILLS_TOOLSET_ENABLED")
3014
- directories_present, directories_env = _env_list("VDS_AUDIT_LLM__SKILLS_DIRECTORIES")
3015
- allowlist_present, allowlist_env = _env_list("VDS_AUDIT_LLM__SKILLS_ALLOWLIST")
3016
- allowed_tiers_present, allowed_tiers_env = _env_list("VDS_AUDIT_LLM__SKILLS_ALLOWED_TRUST_TIERS")
3017
- allow_script_present, allow_script_env = _env_bool("VDS_AUDIT_LLM__SKILLS_ALLOW_SCRIPT_EXECUTION")
3018
- trust_tiers_present, trust_tiers_env = _env_trust_tier_map("VDS_AUDIT_LLM__SKILLS_TRUST_TIERS")
3019
- default_tier_raw = os.getenv("VDS_AUDIT_LLM__SKILLS_DEFAULT_TRUST_TIER")
3020
- default_tier_present = default_tier_raw is not None
3021
- default_tier_env = str(default_tier_raw or "").strip()
3022
- try:
3023
- from vds_audit_orchestrator.config import get_config
3024
-
3025
- llm_cfg = get_config().llm
3026
- except Exception:
3027
- llm_cfg = None
3028
-
3029
- policy = dict(defaults)
3030
- if llm_cfg is not None:
3031
- policy["enabled"] = bool(getattr(llm_cfg, "skills_toolset_enabled", False))
3032
- policy["directories"] = [
3033
- str(item).strip() for item in (getattr(llm_cfg, "skills_directories", []) or []) if str(item).strip()
3034
- ]
3035
- policy["allowlist"] = [
3036
- str(item).strip() for item in (getattr(llm_cfg, "skills_allowlist", []) or []) if str(item).strip()
3037
- ]
3038
- policy["allowed_trust_tiers"] = [
3039
- str(item).strip()
3040
- for item in (getattr(llm_cfg, "skills_allowed_trust_tiers", []) or [])
3041
- if str(item).strip()
3042
- ]
3043
- trust_tiers_cfg: dict[str, str] = {}
3044
- for raw_name, raw_tier in dict(getattr(llm_cfg, "skills_trust_tiers", {}) or {}).items():
3045
- normalized = self._normalize_skill_identifier(str(raw_name))
3046
- tier_value = str(raw_tier).strip()
3047
- if normalized and tier_value:
3048
- trust_tiers_cfg[normalized] = tier_value
3049
- policy["trust_tiers"] = trust_tiers_cfg
3050
- default_tier_cfg = str(getattr(llm_cfg, "skills_default_trust_tier", "external-unverified")).strip()
3051
- policy["default_trust_tier"] = default_tier_cfg or "external-unverified"
3052
- policy["allow_script_execution"] = bool(getattr(llm_cfg, "skills_allow_script_execution", False))
3053
-
3054
- # Environment/profile overrides must remain authoritative for runtime behavior.
3055
- if enabled_present:
3056
- policy["enabled"] = enabled_env
3057
- if directories_present:
3058
- policy["directories"] = directories_env
3059
- if allowlist_present:
3060
- policy["allowlist"] = allowlist_env
3061
- if allowed_tiers_present:
3062
- policy["allowed_trust_tiers"] = allowed_tiers_env
3063
- if trust_tiers_present:
3064
- policy["trust_tiers"] = trust_tiers_env
3065
- if default_tier_present and default_tier_env:
3066
- policy["default_trust_tier"] = default_tier_env
3067
- if allow_script_present:
3068
- policy["allow_script_execution"] = allow_script_env
3069
- resolved_directories = _normalize_skill_directories([str(item) for item in (policy.get("directories") or [])])
3070
- if not resolved_directories:
3071
- try:
3072
- from vds_audit_orchestrator.agents.toolsets.skills_toolset import DEFAULT_AUDIT_SKILLS
3073
- except Exception:
3074
- DEFAULT_AUDIT_SKILLS = []
3075
- resolved_directories = _normalize_skill_directories([str(item) for item in (DEFAULT_AUDIT_SKILLS or [])])
3076
- policy["directories"] = resolved_directories
3077
- return policy
3078
-
3079
- @staticmethod
3080
- def _collect_skills_metadata(
3081
- *,
3082
- directories: list[str],
3083
- default_trust_tier: Literal["internal", "external-verified", "external-unverified"],
3084
- ) -> list[Any]:
3085
- try:
3086
- from vds_audit_orchestrator.agents.toolsets.skills_toolset import (
3087
- SkillsToolsetConfig,
3088
- get_skills_metadata,
3089
- )
3090
- except Exception:
3091
- return []
3092
- try:
3093
- return list(
3094
- get_skills_metadata(
3095
- SkillsToolsetConfig(
3096
- directories=directories,
3097
- default_trust_tier=default_trust_tier,
3098
- )
3099
- )
3100
- )
3101
- except Exception:
3102
- return []
3103
-
3104
- def _build_skills_catalog(self, *, force_refresh: bool = False) -> list[dict[str, Any]]:
3105
- if self._skills_catalog_cache is not None and not force_refresh:
3106
- return list(self._skills_catalog_cache)
3107
-
3108
- policy = self._resolve_skills_runtime_policy()
3109
- if not bool(policy.get("enabled")):
3110
- self._skills_catalog_cache = []
3111
- return []
3112
-
3113
- directories = [str(item).strip() for item in (policy.get("directories") or []) if str(item).strip()]
3114
- if not directories:
3115
- self._skills_catalog_cache = []
3116
- return []
3117
-
3118
- metadata = self._collect_skills_metadata(
3119
- directories=directories,
3120
- default_trust_tier=cast(
3121
- "Literal['internal', 'external-verified', 'external-unverified']",
3122
- str(policy.get("default_trust_tier") or "external-unverified"),
3123
- ),
3124
- )
3125
- allowlist = {
3126
- self._normalize_skill_identifier(item)
3127
- for item in (policy.get("allowlist") or [])
3128
- if self._normalize_skill_identifier(str(item))
3129
- }
3130
- allowed_trust_tiers = {
3131
- str(item).strip() for item in (policy.get("allowed_trust_tiers") or []) if str(item).strip()
3132
- }
3133
- trust_tier_overrides = {
3134
- self._normalize_skill_identifier(str(name)): str(tier).strip()
3135
- for name, tier in dict(policy.get("trust_tiers") or {}).items()
3136
- if self._normalize_skill_identifier(str(name)) and str(tier).strip()
3137
- }
3138
- default_trust_tier = str(policy.get("default_trust_tier") or "external-unverified")
3139
-
3140
- catalog: list[dict[str, Any]] = []
3141
- seen: set[str] = set()
3142
- for item in metadata:
3143
- canonical_name = str(
3144
- getattr(item, "name", None)
3145
- or getattr(item, "canonical_name", None)
3146
- or getattr(item, "frontmatter_name", None)
3147
- or getattr(item, "metadata_name", None)
3148
- or ""
3149
- ).strip()
3150
- if not canonical_name:
3151
- continue
3152
- aliases = self._build_skill_aliases(
3153
- canonical_name,
3154
- str(getattr(item, "metadata_name", "") or ""),
3155
- str(getattr(item, "frontmatter_name", "") or ""),
3156
- str(getattr(item, "runtime_name", "") or ""),
3157
- str(getattr(item, "canonical_name", "") or ""),
3158
- )
3159
- if allowlist and aliases.isdisjoint(allowlist):
3160
- continue
3161
-
3162
- trust_tier = str(getattr(item, "trust_tier", "") or "").strip() or default_trust_tier
3163
- for alias in aliases:
3164
- normalized_alias = self._normalize_skill_identifier(alias)
3165
- if normalized_alias in trust_tier_overrides:
3166
- trust_tier = trust_tier_overrides[normalized_alias]
3167
- break
3168
- if allowed_trust_tiers and trust_tier not in allowed_trust_tiers:
3169
- continue
3170
-
3171
- path_value = str(getattr(item, "path", "") or "").strip()
3172
- if not path_value:
3173
- continue
3174
- path_obj = Path(path_value).expanduser().resolve()
3175
- if not path_obj.is_dir():
3176
- continue
3177
-
3178
- normalized_name = self._normalize_skill_identifier(canonical_name)
3179
- if normalized_name in seen:
3180
- continue
3181
- seen.add(normalized_name)
3182
- catalog.append(
3183
- {
3184
- "name": canonical_name,
3185
- "description": str(getattr(item, "description", "") or "") or None,
3186
- "trust_tier": trust_tier,
3187
- "path": str(path_obj),
3188
- "has_scripts": bool(getattr(item, "has_scripts", False)),
3189
- "content_hash": str(getattr(item, "content_hash", "") or "") or None,
3190
- "aliases": aliases,
3191
- }
3192
- )
3193
-
3194
- catalog.sort(key=lambda row: str(row.get("name") or "").lower())
3195
- self._skills_catalog_cache = catalog
3196
- return list(catalog)
3197
-
3198
- def _find_skill_entry(self, skill_name: str) -> dict[str, Any] | None:
3199
- normalized_query = self._normalize_skill_identifier(skill_name)
3200
- if not normalized_query:
3201
- return None
3202
- catalog = self._build_skills_catalog()
3203
- for entry in catalog:
3204
- aliases = {
3205
- self._normalize_skill_identifier(alias)
3206
- for alias in (entry.get("aliases") or set())
3207
- if self._normalize_skill_identifier(str(alias))
3208
- }
3209
- if normalized_query in aliases:
3210
- return entry
3211
-
3212
- for entry in catalog:
3213
- name = self._normalize_skill_identifier(str(entry.get("name") or ""))
3214
- if normalized_query in name:
3215
- return entry
3216
- return None
3217
-
3218
- @staticmethod
3219
- def _clip_text(content: str, *, max_chars: int) -> str:
3220
- if len(content) <= max_chars:
3221
- return content
3222
- return content[:max_chars]
3223
-
3224
- @staticmethod
3225
- def _enumerate_skill_assets(skill_dir: Path) -> tuple[list[str], list[str]]:
3226
- resources: list[str] = []
3227
- scripts: list[str] = []
3228
-
3229
- skill_md = skill_dir / "SKILL.md"
3230
- if skill_md.is_file():
3231
- resources.append("SKILL.md")
3232
-
3233
- for folder_name in ("references", "assets"):
3234
- folder = skill_dir / folder_name
3235
- if not folder.is_dir():
3236
- continue
3237
- for path in sorted(folder.rglob("*")):
3238
- if not path.is_file():
3239
- continue
3240
- resources.append(path.relative_to(skill_dir).as_posix())
3241
- if len(resources) >= 80:
3242
- break
3243
- if len(resources) >= 80:
3244
- break
3245
-
3246
- scripts_dir = skill_dir / "scripts"
3247
- if scripts_dir.is_dir():
3248
- for path in sorted(scripts_dir.rglob("*")):
3249
- if not path.is_file():
3250
- continue
3251
- scripts.append(path.relative_to(skill_dir).as_posix())
3252
- if len(scripts) >= 50:
3253
- break
3254
- return resources, scripts
3255
-
3256
- @staticmethod
3257
- def _resolve_path_in_skill(
3258
- *,
3259
- skill_dir: Path,
3260
- relative_or_absolute: str,
3261
- ) -> tuple[Path | None, str | None]:
3262
- raw = Path(relative_or_absolute)
3263
- target = raw.expanduser().resolve() if raw.is_absolute() else (skill_dir / raw).resolve()
3264
- try:
3265
- target.relative_to(skill_dir)
3266
- except ValueError:
3267
- return None, "path_traversal_denied"
3268
- if not target.is_file():
3269
- return None, "resource_not_found"
3270
- return target, None
3271
-
3272
- @staticmethod
3273
- def _resolve_skill_resource_candidates(resource_path: str) -> list[str]:
3274
- normalized = str(resource_path or "").strip()
3275
- if not normalized:
3276
- return ["SKILL.md"]
3277
- normalized_key = normalized.replace("\\", "/").strip().lower()
3278
- if normalized_key in {"@row-analysis", "row-analysis", "row_analysis", "references/row-analysis.md"}:
3279
- return ["references/row-analysis.md", "SKILL.md"]
3280
- if normalized_key in {"detect-migrations", "detect_migrations", "@detect-migrations"}:
3281
- return ["references/detection-strategy.md", "references/row-analysis.md", "SKILL.md"]
3282
- return [normalized]
3283
-
3284
- @staticmethod
3285
- def _is_actionable_skill_resource_path(resource_path: Any) -> bool:
3286
- normalized = str(resource_path or "").strip().replace("\\", "/").lower()
3287
- if not normalized:
3288
- return False
3289
- if normalized.endswith("/skill.md") or normalized == "skill.md":
3290
- return False
3291
- if "row-analysis" in normalized:
3292
- return True
3293
- return normalized.startswith("references/")
3294
-
3295
- def _list_skills(self, request: ListSkillsInput) -> ListSkillsOutput:
3296
- query = str(request.query or "").strip().lower()
3297
- items: list[SkillInfo] = []
3298
- for entry in self._build_skills_catalog():
3299
- name = str(entry.get("name") or "")
3300
- description = str(entry.get("description") or "")
3301
- if query and query not in name.lower() and query not in description.lower():
3302
- continue
3303
- items.append(
3304
- SkillInfo(
3305
- name=name,
3306
- description=description or None,
3307
- trust_tier=str(entry.get("trust_tier") or "") or None,
3308
- has_scripts=bool(entry.get("has_scripts", False)),
3309
- path=str(entry.get("path") or ""),
3310
- )
3311
- )
3312
- if len(items) >= request.limit:
3313
- break
3314
- self._record_skill_tool_usage(
3315
- {
3316
- "tool": ToolName.LIST_SKILLS.value,
3317
- "query": request.query,
3318
- "results_count": len(items),
3319
- "success": True,
3320
- "effective": len(items) > 0,
3321
- }
3322
- )
3323
- return ListSkillsOutput(skills=items)
3324
-
3325
- def _load_skill(self, request: LoadSkillInput) -> LoadSkillOutput:
3326
- entry = self._find_skill_entry(request.name)
3327
- if entry is None:
3328
- self._record_skill_tool_usage(
3329
- {
3330
- "tool": ToolName.LOAD_SKILL.value,
3331
- "skill": request.name,
3332
- "success": False,
3333
- "effective": False,
3334
- "error": "skill_not_found",
3335
- }
3336
- )
3337
- return LoadSkillOutput(
3338
- name=request.name,
3339
- found=False,
3340
- error="skill_not_found",
3341
- )
3342
-
3343
- skill_dir = Path(str(entry.get("path") or "")).resolve()
3344
- resources, scripts = self._enumerate_skill_assets(skill_dir)
3345
- output = LoadSkillOutput(
3346
- name=request.name,
3347
- found=True,
3348
- resolved_name=str(entry.get("name") or request.name),
3349
- path=str(skill_dir),
3350
- description=str(entry.get("description") or "") or None,
3351
- trust_tier=str(entry.get("trust_tier") or "") or None,
3352
- has_scripts=bool(entry.get("has_scripts", False)),
3353
- resources=resources,
3354
- scripts=scripts,
3355
- content_hash=str(entry.get("content_hash") or "") or None,
3356
- )
3357
- self._record_skill_tool_usage(
3358
- {
3359
- "tool": ToolName.LOAD_SKILL.value,
3360
- "skill": output.resolved_name,
3361
- "success": True,
3362
- "effective": bool(resources or scripts),
3363
- }
3364
- )
3365
- return output
3366
-
3367
- def _read_skill_resource(self, request: ReadSkillResourceInput) -> ReadSkillResourceOutput:
3368
- entry = self._find_skill_entry(request.name)
3369
- requested_resource_path = str(request.resource_path or "").strip() or "SKILL.md"
3370
- if entry is None:
3371
- self._record_skill_tool_usage(
3372
- {
3373
- "tool": ToolName.READ_SKILL_RESOURCE.value,
3374
- "skill": request.name,
3375
- "resource": requested_resource_path,
3376
- "requested_resource": requested_resource_path,
3377
- "success": False,
3378
- "effective": False,
3379
- "error": "skill_not_found",
3380
- }
3381
- )
3382
- return ReadSkillResourceOutput(
3383
- name=request.name,
3384
- resource_path=requested_resource_path,
3385
- success=False,
3386
- error="skill_not_found",
3387
- )
3388
-
3389
- skill_dir = Path(str(entry.get("path") or "")).resolve()
3390
- target: Path | None = None
3391
- error: str | None = None
3392
- resolved_resource_path = requested_resource_path
3393
- for candidate in self._resolve_skill_resource_candidates(requested_resource_path):
3394
- maybe_target, maybe_error = self._resolve_path_in_skill(
3395
- skill_dir=skill_dir,
3396
- relative_or_absolute=candidate,
3397
- )
3398
- if maybe_target is not None:
3399
- target = maybe_target
3400
- resolved_resource_path = candidate
3401
- error = None
3402
- break
3403
- if maybe_error and error is None:
3404
- error = maybe_error
3405
- if target is None:
3406
- self._record_skill_tool_usage(
3407
- {
3408
- "tool": ToolName.READ_SKILL_RESOURCE.value,
3409
- "skill": str(entry.get("name") or request.name),
3410
- "resource": requested_resource_path,
3411
- "requested_resource": requested_resource_path,
3412
- "success": False,
3413
- "effective": False,
3414
- "error": error or "resource_not_found",
3415
- }
3416
- )
3417
- return ReadSkillResourceOutput(
3418
- name=str(entry.get("name") or request.name),
3419
- resource_path=requested_resource_path,
3420
- success=False,
3421
- error=error or "resource_not_found",
3422
- )
3423
-
3424
- try:
3425
- content = target.read_text(encoding="utf-8", errors="replace")
3426
- except OSError as exc:
3427
- self._record_skill_tool_usage(
3428
- {
3429
- "tool": ToolName.READ_SKILL_RESOURCE.value,
3430
- "skill": str(entry.get("name") or request.name),
3431
- "resource": resolved_resource_path,
3432
- "requested_resource": requested_resource_path,
3433
- "success": False,
3434
- "effective": False,
3435
- "error": f"read_failed:{exc}",
3436
- }
3437
- )
3438
- return ReadSkillResourceOutput(
3439
- name=str(entry.get("name") or request.name),
3440
- resource_path=resolved_resource_path,
3441
- success=False,
3442
- error="resource_read_failed",
3443
- )
3444
-
3445
- clipped = self._clip_text(content, max_chars=request.max_chars)
3446
- informational = bool(clipped.strip())
3447
- effective = informational and self._is_actionable_skill_resource_path(resolved_resource_path)
3448
- skill_name = str(entry.get("name") or request.name)
3449
- resource_fell_back = resolved_resource_path != requested_resource_path
3450
- self._record_skill_tool_usage(
3451
- {
3452
- "tool": ToolName.READ_SKILL_RESOURCE.value,
3453
- "skill": skill_name,
3454
- "resource": resolved_resource_path,
3455
- "requested_resource": requested_resource_path,
3456
- "success": True,
3457
- "effective": effective,
3458
- "informational": informational,
3459
- "benefit_signal": effective,
3460
- "content_length": len(clipped),
3461
- }
3462
- )
3463
- # P172-F (TSK-172.36): emit observable fallback event when SKILL.md served instead of
3464
- # the requested resource, so callers can surface silent fallbacks in telemetry.
3465
- if resource_fell_back:
3466
- self._record_skill_tool_usage(
3467
- {
3468
- "event": "skill_resource_fallback",
3469
- "tool": ToolName.READ_SKILL_RESOURCE.value,
3470
- "skill_name": skill_name,
3471
- "requested_resource": requested_resource_path,
3472
- "actual_resource": resolved_resource_path,
3473
- "fallback_reason": "requested_resource_missing",
3474
- }
3475
- )
3476
- return ReadSkillResourceOutput(
3477
- name=skill_name,
3478
- resource_path=resolved_resource_path,
3479
- success=True,
3480
- content=clipped,
3481
- ref=str(target),
3482
- requested_resource_fallback=resource_fell_back,
3483
- fallback_reason="requested_resource_missing" if resource_fell_back else None,
3484
- )
3485
-
3486
- def _run_skill_script(self, request: RunSkillScriptInput) -> RunSkillScriptOutput:
3487
- policy = self._resolve_skills_runtime_policy()
3488
- if not bool(policy.get("allow_script_execution")):
3489
- self._record_skill_tool_usage(
3490
- {
3491
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3492
- "skill": request.name,
3493
- "script": request.script_path,
3494
- "success": False,
3495
- "effective": False,
3496
- "error": "script_execution_disabled",
3497
- }
3498
- )
3499
- return RunSkillScriptOutput(
3500
- name=request.name,
3501
- script_path=request.script_path,
3502
- success=False,
3503
- error="script_execution_disabled",
3504
- )
3505
-
3506
- entry = self._find_skill_entry(request.name)
3507
- if entry is None:
3508
- self._record_skill_tool_usage(
3509
- {
3510
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3511
- "skill": request.name,
3512
- "script": request.script_path,
3513
- "success": False,
3514
- "effective": False,
3515
- "error": "skill_not_found",
3516
- }
3517
- )
3518
- return RunSkillScriptOutput(
3519
- name=request.name,
3520
- script_path=request.script_path,
3521
- success=False,
3522
- error="skill_not_found",
3523
- )
3524
-
3525
- skill_dir = Path(str(entry.get("path") or "")).resolve()
3526
- script_path, error = self._resolve_path_in_skill(
3527
- skill_dir=skill_dir,
3528
- relative_or_absolute=request.script_path,
3529
- )
3530
- if script_path is None:
3531
- self._record_skill_tool_usage(
3532
- {
3533
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3534
- "skill": str(entry.get("name") or request.name),
3535
- "script": request.script_path,
3536
- "success": False,
3537
- "effective": False,
3538
- "error": error or "script_not_found",
3539
- }
3540
- )
3541
- return RunSkillScriptOutput(
3542
- name=str(entry.get("name") or request.name),
3543
- script_path=request.script_path,
3544
- success=False,
3545
- error=error or "script_not_found",
3546
- )
3547
-
3548
- command = [str(script_path), *request.args]
3549
- try:
3550
- completed = subprocess.run(
3551
- command,
3552
- check=False,
3553
- capture_output=True,
3554
- text=True,
3555
- timeout=request.timeout_seconds,
3556
- )
3557
- except subprocess.TimeoutExpired:
3558
- self._record_skill_tool_usage(
3559
- {
3560
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3561
- "skill": str(entry.get("name") or request.name),
3562
- "script": request.script_path,
3563
- "success": False,
3564
- "effective": False,
3565
- "error": "timeout",
3566
- }
3567
- )
3568
- return RunSkillScriptOutput(
3569
- name=str(entry.get("name") or request.name),
3570
- script_path=request.script_path,
3571
- success=False,
3572
- error="script_timeout",
3573
- )
3574
- except OSError as exc:
3575
- self._record_skill_tool_usage(
3576
- {
3577
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3578
- "skill": str(entry.get("name") or request.name),
3579
- "script": request.script_path,
3580
- "success": False,
3581
- "effective": False,
3582
- "error": f"execution_error:{exc}",
3583
- }
3584
- )
3585
- return RunSkillScriptOutput(
3586
- name=str(entry.get("name") or request.name),
3587
- script_path=request.script_path,
3588
- success=False,
3589
- error="script_execution_failed",
3590
- )
3591
-
3592
- stdout = self._clip_text(str(completed.stdout or ""), max_chars=6000)
3593
- stderr = self._clip_text(str(completed.stderr or ""), max_chars=4000)
3594
- success = completed.returncode == 0
3595
- self._record_skill_tool_usage(
3596
- {
3597
- "tool": ToolName.RUN_SKILL_SCRIPT.value,
3598
- "skill": str(entry.get("name") or request.name),
3599
- "script": request.script_path,
3600
- "success": success,
3601
- "effective": bool(success and stdout.strip()),
3602
- "returncode": completed.returncode,
3603
- }
3604
- )
3605
- return RunSkillScriptOutput(
3606
- name=str(entry.get("name") or request.name),
3607
- script_path=request.script_path,
3608
- success=success,
3609
- stdout=stdout,
3610
- stderr=stderr,
3611
- returncode=int(completed.returncode),
3612
- error=None if success else "script_failed",
3613
- )
3614
-
3615
- def _get_doc_query_adapter(self) -> StateBackedEvidenceQueryAdapter:
3616
- if self._doc_query_adapter is None:
3617
- self._doc_query_adapter = StateBackedEvidenceQueryAdapter(state_dsn=self._state_dsn)
3618
- return self._doc_query_adapter
3619
-
3620
- def _get_state_store(self) -> PostgresStateStore:
3621
- if self._state_store is None:
3622
- self._state_store = PostgresStateStore(self._state_dsn)
3623
- return self._state_store
3624
-
3625
- def _resolve_repo_root(self, *, require_exists: bool) -> Path:
3626
- repo_root = Path(self._repo_path).resolve() if self._repo_path else None
3627
- if repo_root is None:
3628
- raise ToolExecutionError(
3629
- "missing_runtime_context",
3630
- "repo_path is required for code tools",
3631
- details={"required": ["repo_path"]},
3632
- )
3633
- if require_exists and (not repo_root.exists() or not repo_root.is_dir()):
3634
- raise ToolExecutionError(
3635
- "repo_path_not_found",
3636
- "Configured repo_path does not exist or is not a directory",
3637
- details={"repo_path": self._repo_path},
3638
- )
3639
- return repo_root
3640
-
3641
- @staticmethod
3642
- def _split_rg_line(line: str) -> tuple[str | None, str | None, str]:
3643
- parts = line.split(":", 2)
3644
- if len(parts) != 3:
3645
- return None, None, ""
3646
- return parts[0], parts[1], parts[2]
3647
-
3648
- @staticmethod
3649
- def _extract_doc_ref_candidates(ref: str) -> dict[str, str]:
3650
- normalized = str(ref or "").strip()
3651
- if not normalized:
3652
- return {}
3653
- if normalized.startswith("chunk:"):
3654
- return {"chunk_id": normalized.removeprefix("chunk:").strip()}
3655
- if normalized.startswith("source_uri:"):
3656
- return {"source_uri": normalized.removeprefix("source_uri:").strip()}
3657
- if normalized.startswith("document_id:"):
3658
- return {"document_id": normalized.removeprefix("document_id:").strip()}
3659
- if "://" in normalized:
3660
- try:
3661
- page_id = parse_qs(urlparse(normalized).query).get("pageId", [None])[0]
3662
- except Exception:
3663
- page_id = None
3664
- if page_id and str(page_id).strip().isdigit():
3665
- return {"document_id": str(page_id).strip()}
3666
- return {"source_uri": normalized}
3667
- return {"document_id": normalized}
3668
-
3669
- def _lookup_doc_chunk(
3670
- self,
3671
- *,
3672
- chunk_id: str | None,
3673
- source_uri: str | None,
3674
- document_id: str | None,
3675
- repo_key: str | None,
3676
- ) -> Mapping[str, Any] | None:
3677
- store = self._get_state_store()
3678
- with store._conn.cursor() as cur:
3679
- cur.execute(
3680
- """
3681
- WITH scoped_project AS (
3682
- SELECT id
3683
- FROM audit_state.projects
3684
- WHERE project_key = %s
3685
- LIMIT 1
3686
- ),
3687
- scoped_repo AS (
3688
- SELECT repos.id
3689
- FROM audit_state.repos AS repos
3690
- JOIN scoped_project
3691
- ON scoped_project.id = repos.project_id
3692
- WHERE %s::text IS NOT NULL
3693
- AND repos.repo_key = %s
3694
- LIMIT 1
3695
- )
3696
- SELECT
3697
- d.document_id,
3698
- d.source_uri,
3699
- d.source_type,
3700
- d.page_id,
3701
- d.metadata AS document_metadata,
3702
- c.chunk_id,
3703
- c.content_text
3704
- FROM audit_state.corpus_documents AS d
3705
- JOIN audit_state.corpus_chunks AS c
3706
- ON c.document_pk = d.id
3707
- JOIN audit_state.retrieval_snapshots AS s
3708
- ON s.id = d.snapshot_id
3709
- WHERE d.project_id = (SELECT id FROM scoped_project)
3710
- AND (
3711
- %s::text IS NULL
3712
- OR d.repo_id = (SELECT id FROM scoped_repo)
3713
- OR (d.repo_id IS NULL AND d.source_type NOT IN ('code_file', 'ops_repo_file'))
3714
- )
3715
- AND (
3716
- (%s::text IS NOT NULL AND c.chunk_id = %s)
3717
- OR (%s::text IS NOT NULL AND d.source_uri = %s)
3718
- OR (%s::text IS NOT NULL AND d.document_id = %s)
3719
- )
3720
- ORDER BY s.created_at DESC, s.id DESC, d.document_id ASC, c.chunk_id ASC
3721
- LIMIT 1
3722
- """,
3723
- (
3724
- self._project_key,
3725
- repo_key,
3726
- repo_key,
3727
- repo_key,
3728
- chunk_id,
3729
- chunk_id,
3730
- source_uri,
3731
- source_uri,
3732
- document_id,
3733
- document_id,
3734
- ),
3735
- )
3736
- return cur.fetchone()
3737
-
3738
- @classmethod
3739
- def _is_excluded_docs_artifact(
3740
- cls,
3741
- *,
3742
- source_uri: str | None,
3743
- document_id: str | None,
3744
- source_type: str | None = None,
3745
- metadata: Mapping[str, Any] | None = None,
3746
- ) -> bool:
3747
- metadata_map = metadata if isinstance(metadata, Mapping) else {}
3748
- source_type_candidates = {
3749
- str(source_type or "").strip().lower(),
3750
- str(metadata_map.get("source_type") or "").strip().lower(),
3751
- str(metadata_map.get("resource_type") or "").strip().lower(),
3752
- }
3753
- source_type_candidates.discard("")
3754
- if source_type_candidates & cls._DOC_EXCLUDED_SOURCE_TYPES:
3755
- return True
3756
-
3757
- doc_class = str(metadata_map.get("doc_class") or "").strip().lower()
3758
- if doc_class in cls._DOC_EXCLUDED_DOC_CLASSES or "code" in doc_class:
3759
- return True
3760
-
3761
- source_uri_text = str(source_uri or "").strip().lower()
3762
- document_id_text = str(document_id or "").strip().lower()
3763
- if source_uri_text.startswith("repo://") or source_uri_text.startswith("bitbucket://"):
3764
- return True
3765
-
3766
- candidates = (
3767
- source_uri_text,
3768
- document_id_text,
3769
- str(metadata_map.get("file_path") or "").strip().lower(),
3770
- str(metadata_map.get("source_path") or "").strip().lower(),
3771
- str(metadata_map.get("source_uri") or "").strip().lower(),
3772
- str(metadata_map.get("title") or "").strip().lower(),
3773
- str(metadata_map.get("page_title") or "").strip().lower(),
3774
- str(metadata_map.get("source_page_title") or "").strip().lower(),
3775
- str(metadata_map.get("document_title") or "").strip().lower(),
3776
- )
3777
- haystack = " ".join(item for item in candidates if item)
3778
- return any(marker in haystack for marker in cls._DOC_EXCLUDED_PATH_MARKERS)
3779
-
3780
- @classmethod
3781
- def _is_hash_only_document_without_source(cls, *, source_uri: str | None, document_id: str | None) -> bool:
3782
- """Filter synthetic hash IDs that lack a resolvable source URI.
3783
-
3784
- These IDs commonly originate from generated artifacts and frequently fail
3785
- `read_doc_chunk` with `doc_chunk_excluded`, causing low-value tool loops.
3786
- """
3787
- source = str(source_uri or "").strip()
3788
- if source:
3789
- return False
3790
- doc_id = str(document_id or "").strip().lower()
3791
- if not doc_id:
3792
- return False
3793
- return bool(cls._SYNTHETIC_DOCUMENT_ID_PATTERN.fullmatch(doc_id))
3794
-
3795
- @classmethod
3796
- def _resolve_repo_file(
3797
- cls,
3798
- *,
3799
- repo_root: Path,
3800
- path_value: str,
3801
- allow_project_parent: bool = False,
3802
- ) -> Path:
3803
- candidate = Path(path_value)
3804
- resolved = candidate.resolve() if candidate.is_absolute() else (repo_root / candidate).resolve()
3805
- try:
3806
- resolved.relative_to(repo_root)
3807
- except ValueError:
3808
- # Allow paths within the project-level parent when requested (DD-123.11).
3809
- if allow_project_parent:
3810
- project_parent = cls._derive_project_parent(repo_root)
3811
- if project_parent is not None:
3812
- try:
3813
- resolved.relative_to(project_parent)
3814
- return resolved
3815
- except ValueError:
3816
- pass
3817
- raise ToolExecutionError(
3818
- "path_traversal_denied",
3819
- "Requested path escapes configured repository root",
3820
- details={"path": path_value, "repo_path": str(repo_root)},
3821
- ) from None
3822
- return resolved